From 47e227f6f46d7ab3940b14ea06b2174ef74c2af7 Mon Sep 17 00:00:00 2001 From: Tasos Bekos Date: Tue, 7 Jan 2014 17:47:38 +0100 Subject: [PATCH] feat(rating): plug into `ngModel` controller Closes #1546 BREAKING CHANGE: `rating` is now integrated with `ngModelController`. * `value` is replaced from `ng-model`. Before: After: --- src/rating/docs/demo.html | 6 ++--- src/rating/docs/readme.md | 5 +++-- src/rating/rating.js | 41 +++++++++++++++++++++++----------- src/rating/test/rating.spec.js | 18 +++++++-------- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/rating/docs/demo.html b/src/rating/docs/demo.html index 3f2f2bbe5f..142099d712 100644 --- a/src/rating/docs/demo.html +++ b/src/rating/docs/demo.html @@ -1,6 +1,6 @@

Default

- + {{percent}}%
Rate: {{rate}} - Readonly is: {{isReadonly}} - Hovering over: {{overStar || "none"}}
@@ -10,6 +10,6 @@

Default


Custom icons

-
(Rate: {{x}})
-
(Rate: {{y}})
+
(Rate: {{x}})
+
(Rate: {{y}})
\ No newline at end of file diff --git a/src/rating/docs/readme.md b/src/rating/docs/readme.md index 78a2d79e2d..310e6bfe9a 100644 --- a/src/rating/docs/readme.md +++ b/src/rating/docs/readme.md @@ -4,7 +4,8 @@ Rating directive that will take care of visualising a star rating bar. #### `` #### - * `value` +<<<<<<< HEAD + * `ng-model` : The current rate. @@ -12,7 +13,7 @@ Rating directive that will take care of visualising a star rating bar. _(Defaults: 5)_ : Changes the number of icons. - * `readonly` + * `readonly` _(Defaults: false)_ : Prevent user's interaction. diff --git a/src/rating/rating.js b/src/rating/rating.js index 56440bdd18..778d03f83e 100644 --- a/src/rating/rating.js +++ b/src/rating/rating.js @@ -7,12 +7,22 @@ angular.module('ui.bootstrap.rating', []) }) .controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { + var ngModelCtrl = {$setViewValue: angular.noop}; this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + $scope.range = this.buildTemplateObjects( + angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : new Array(this.maxRange) + ); + }; - this.createRateObjects = function(states) { + this.buildTemplateObjects = function(states) { var defaultOptions = { stateOn: this.stateOn, stateOff: this.stateOff @@ -24,12 +34,10 @@ angular.module('ui.bootstrap.rating', []) return states; }; - // Get objects used in template - $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange)); - $scope.rate = function(value) { - if ( $scope.value !== value && !$scope.readonly ) { - $scope.value = value; + if ( !$scope.readonly ) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); } }; @@ -41,13 +49,13 @@ angular.module('ui.bootstrap.rating', []) }; $scope.reset = function() { - $scope.val = angular.copy($scope.value); + $scope.val = ngModelCtrl.$viewValue; $scope.onLeave(); }; - - $scope.$watch('value', function(value) { - $scope.val = value; - }); + + this.render = function() { + $scope.val = ngModelCtrl.$viewValue; + }; $scope.readonly = false; if ($attrs.readonly) { @@ -60,13 +68,20 @@ angular.module('ui.bootstrap.rating', []) .directive('rating', function() { return { restrict: 'EA', + require: ['rating', 'ngModel'], scope: { - value: '=', onHover: '&', onLeave: '&' }, controller: 'RatingController', templateUrl: 'template/rating/rating.html', - replace: true + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + ratingCtrl.init( ngModelCtrl ); + } + } }; }); \ No newline at end of file diff --git a/src/rating/test/rating.spec.js b/src/rating/test/rating.spec.js index bf880ed439..f4253b3826 100644 --- a/src/rating/test/rating.spec.js +++ b/src/rating/test/rating.spec.js @@ -6,7 +6,7 @@ describe('rating directive', function () { $compile = _$compile_; $rootScope = _$rootScope_; $rootScope.rate = 3; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -71,7 +71,7 @@ describe('rating directive', function () { }); it('shows different number of icons when `max` attribute is set', function() { - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getStars().length).toBe(7); @@ -79,14 +79,14 @@ describe('rating directive', function () { it('shows different number of icons when `max` attribute is from scope variable', function() { $rootScope.max = 15; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getStars().length).toBe(15); }); it('handles readonly attribute', function() { $rootScope.isReadonly = true; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); expect(getState()).toEqual([true, true, true, false, false]); @@ -106,7 +106,7 @@ describe('rating directive', function () { it('should fire onHover', function() { $rootScope.hoveringOver = jasmine.createSpy('hoveringOver'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); getStar(3).trigger('mouseover'); @@ -116,7 +116,7 @@ describe('rating directive', function () { it('should fire onLeave', function() { $rootScope.leaving = jasmine.createSpy('leaving'); - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); element.trigger('mouseleave'); @@ -128,7 +128,7 @@ describe('rating directive', function () { beforeEach(inject(function() { $rootScope.classOn = 'icon-ok-sign'; $rootScope.classOff = 'icon-ok-circle'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -145,7 +145,7 @@ describe('rating directive', function () { {stateOn: 'heart'}, {stateOff: 'off'} ]; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); @@ -175,7 +175,7 @@ describe('rating directive', function () { ratingConfig.max = 10; ratingConfig.stateOn = 'on'; ratingConfig.stateOff = 'off'; - element = $compile('')($rootScope); + element = $compile('')($rootScope); $rootScope.$digest(); })); afterEach(inject(function(ratingConfig) {