如何使用angularjs $modal來寫一個公用的彈框插件?望詳解,謝謝。
学习是最好的投资!
我告訴你一個思路,但不會詳解,因為我不喜歡伸手黨……方案給你,最起碼動腦子思考一下吧。
首先,以下程式碼用的不是ui-bootstrap 的$modal, 而是ng-strap 的$modal,原因是我覺得後者的程式碼品質比前者好一些,不過後者比較新,API 沒有前者那麼完善,因此需要你有比較強的動手能力,不過這和接下來要說的擴充$modal service 沒有關係。
其次,擴充一個公用 $modal service 之前你得先考慮一下這些問題:
這些問題在一開始是沒有明確答案的,但你需要在心裡模擬一個答案出來,因為它將決定你的 service 如何寫。
第一步,準備預設的參數;這是原 $modal 提供的參數,先設定好一個初始狀態(依照自己的需求)
javascript// 可以在入口模块的 .config 里做 angular.extend($modalProvider.defaults, { animation: 'am-flip-x', container: 'body', templateUrl: 'components/angular-strap/modal.html' })
javascript
// 可以在入口模块的 .config 里做 angular.extend($modalProvider.defaults, { animation: 'am-flip-x', container: 'body', templateUrl: 'components/angular-strap/modal.html' })
第二步:寫新服務的屬性擴充程式碼;讓新服務可以擁有和原 $modal 一樣的屬性擴充能力
javascript// 一样,放在某个某块的 config 里 .config(function ConfirmModalConfig($modalProvider, ConfirmModalProvider) { ConfirmModalProvider.defaults = angular.extend( $modalProvider.defaults, ConfirmModalProvider.defaults ) })
// 一样,放在某个某块的 config 里 .config(function ConfirmModalConfig($modalProvider, ConfirmModalProvider) { ConfirmModalProvider.defaults = angular.extend( $modalProvider.defaults, ConfirmModalProvider.defaults ) })
接著就是 ConfirmModal 的定義,最終返回的是 $promise,以便於調用者擴展自己的業務邏輯;我在重點處加了些註釋,剩下的自己看明白:
ConfirmModal
javascriptfunction ConfirmModal() { // 新服务的默认参数,允许覆盖 this.defaults = { html: true, templateUrl: 'components/angular-strap/confirm.html', contentTemplate: 'components/angular-strap/confirm-modal.html' } this.$get = function($q, $modal) { return { // 只需一个 public method 足够了 open: function _openConfirmModal(parentScope, options) { // 把调用者的 $scope 传进来,生成新的 $scope 给自己,实现 $scope 继承 // 最大的用处:可以在 $modal 的模版里直接是用 parent $scope 里的属性和方法 var _scope = parentScope.$new() // 给新 $scope 一个 namespace,等价于 angular 的 controller as 语法 _scope.modalModel = {} // 合并默认参数和用户传递的参数 var _options = angular.extend(_.clone(this.defaults), options) _options.scope = _scope // 创造 modal 实例 var _modal = $modal(_options) // 返回 promise,默认给模版绑定两个方法,一个用于确认,一个用于取消 // 如需要更多方法,则可以在 contentTemplate 里调用 parent $scope 的方法 // @params immediateHide: 布尔,用于指明触发默认绑定方法后是自动关闭 $modal, // 还是留给调用者在 .then 里手动关闭 return $q(function(resolve, reject) { _scope.modalModel.confirm = function(data, immediateHide) { if (immediateHide) { _modal.hide() resolve({data: data}) } else resolve({data: data, modal: _modal}) } _scope.modalModel.cancel = function(reason, immediateHide) { if (immediateHide) { _modal.hide() reject({reason: reason}) } else reject({reason: reason, modal: _modal}) } }) }.bind(this) } } }
function ConfirmModal() { // 新服务的默认参数,允许覆盖 this.defaults = { html: true, templateUrl: 'components/angular-strap/confirm.html', contentTemplate: 'components/angular-strap/confirm-modal.html' } this.$get = function($q, $modal) { return { // 只需一个 public method 足够了 open: function _openConfirmModal(parentScope, options) { // 把调用者的 $scope 传进来,生成新的 $scope 给自己,实现 $scope 继承 // 最大的用处:可以在 $modal 的模版里直接是用 parent $scope 里的属性和方法 var _scope = parentScope.$new() // 给新 $scope 一个 namespace,等价于 angular 的 controller as 语法 _scope.modalModel = {} // 合并默认参数和用户传递的参数 var _options = angular.extend(_.clone(this.defaults), options) _options.scope = _scope // 创造 modal 实例 var _modal = $modal(_options) // 返回 promise,默认给模版绑定两个方法,一个用于确认,一个用于取消 // 如需要更多方法,则可以在 contentTemplate 里调用 parent $scope 的方法 // @params immediateHide: 布尔,用于指明触发默认绑定方法后是自动关闭 $modal, // 还是留给调用者在 .then 里手动关闭 return $q(function(resolve, reject) { _scope.modalModel.confirm = function(data, immediateHide) { if (immediateHide) { _modal.hide() resolve({data: data}) } else resolve({data: data, modal: _modal}) } _scope.modalModel.cancel = function(reason, immediateHide) { if (immediateHide) { _modal.hide() reject({reason: reason}) } else reject({reason: reason, modal: _modal}) } }) }.bind(this) } } }
呼叫實例:
javascript// 在某处,通常是 controller 或 directive function SomeWhereController(ConfirmModal, Something, $state) { var vm = this vm.delete = function(something) { ConfirmModal.open($scope, { title: '确定要删除吗?' }) .then(function(result) { return Something.delete(something.id) }) .then(function(response) { $state.reload($state.current) }) .catch(console.error.bind(console)) } }
// 在某处,通常是 controller 或 directive function SomeWhereController(ConfirmModal, Something, $state) { var vm = this vm.delete = function(something) { ConfirmModal.open($scope, { title: '确定要删除吗?' }) .then(function(result) { return Something.delete(something.id) }) .then(function(response) { $state.reload($state.current) }) .catch(console.error.bind(console)) } }
模版什麼的,參考原始的 $modal 自己改寫就是了,代碼 github 上都有,就這樣。
我告訴你一個思路,但不會詳解,因為我不喜歡伸手黨……方案給你,最起碼動腦子思考一下吧。
首先,以下程式碼用的不是ui-bootstrap 的$modal, 而是ng-strap 的$modal,原因是我覺得後者的程式碼品質比前者好一些,不過後者比較新,API 沒有前者那麼完善,因此需要你有比較強的動手能力,不過這和接下來要說的擴充$modal service 沒有關係。
其次,擴充一個公用 $modal service 之前你得先考慮一下這些問題:
這些問題在一開始是沒有明確答案的,但你需要在心裡模擬一個答案出來,因為它將決定你的 service 如何寫。
第一步,準備預設的參數;這是原 $modal 提供的參數,先設定好一個初始狀態(依照自己的需求)
第二步:寫新服務的屬性擴充程式碼;讓新服務可以擁有和原 $modal 一樣的屬性擴充能力
接著就是
ConfirmModal
的定義,最終返回的是 $promise,以便於調用者擴展自己的業務邏輯;我在重點處加了些註釋,剩下的自己看明白:呼叫實例:
模版什麼的,參考原始的 $modal 自己改寫就是了,代碼 github 上都有,就這樣。