Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 70433f8

Browse files
committed
add ngRefRead to read element or controller
1 parent ad31f23 commit 70433f8

File tree

3 files changed

+135
-46
lines changed

3 files changed

+135
-46
lines changed

src/ng/directive/ngRef.js

+28-9
Original file line numberDiff line numberDiff line change
@@ -181,29 +181,48 @@
181181
* </example>
182182
*
183183
*/
184+
185+
var ngRefMinErr = minErr('ngRef');
186+
184187
var ngRefDirective = ['$parse',function($parse) {
185188
return {
186189
priority: -1,
187190
restrict: 'A',
188191
compile: function(tElement, tAttrs) {
189-
// gets the expected controller name, converts <data-some-thing> into "someThing"
192+
// Get the expected controller name, converts <data-some-thing> into "someThing"
190193
var controllerName = directiveNormalize(nodeName_(tElement));
191194

192-
// get the expression for value binding
195+
// Get the expression for value binding
193196
var getter = $parse(tAttrs.ngRef);
194-
var setter = getter.assign;
197+
var setter = getter.assign || function() {
198+
throw ngRefMinErr('nonassign', 'Expression in ngRef="{0}" is non-assignable!', tAttrs.ngRef);
199+
};
195200

196201
return function(scope, element, attrs) {
197-
var refValue = null;
202+
var refValue;
203+
var controller;
198204

199-
if ('ngRefElement' in attrs) {
200-
refValue = element;
205+
if ('ngRefRead' in attrs) {
206+
if (attrs.ngRefRead === '$element') {
207+
refValue = element;
208+
} else {
209+
controller = element.data('$' + attrs.ngRefRead + 'Controller');
210+
if (!controller) {
211+
throw ngRefMinErr(
212+
'noctrl',
213+
'The controller for ngRefRead="{0}" could not be found on ngRef="{1}"',
214+
attrs.ngRefRead,
215+
tAttrs.ngRef
216+
);
217+
}
218+
219+
}
201220
} else {
202-
// gets the controller of the current component or the current DOM element
203-
var controller = element.data('$' + controllerName + 'Controller');
204-
refValue = controller || element;
221+
controller = element.data('$' + controllerName + 'Controller');
205222
}
206223

224+
refValue = refValue || controller || element;
225+
207226
setter(scope, refValue);
208227

209228
// when the element is removed, remove it (nullify it)

test/helpers/matchers.js

+1
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ beforeEach(function() {
313313

314314
function generateCompare(isNot) {
315315
return function(actual, namespace, code, content) {
316+
316317
var matcher = new MinErrMatcher(isNot, namespace, code, content, {
317318
inputType: 'error',
318319
expectedAction: 'equal',

test/ng/directive/ngRefSpec.js

+106-37
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,25 @@
22

33
describe('ngRef', function() {
44

5-
describe('given a component', function() {
5+
describe('on a component', function() {
66

77
var myComponentController, $rootScope, $compile;
88

99
beforeEach(module(function($compileProvider) {
1010
$compileProvider.component('myComponent', {
1111
template: 'foo',
1212
controller: function() {
13+
console.log('ctrl');
1314
myComponentController = this;
1415
}
1516
});
1617
}));
1718

18-
beforeEach(module(function($exceptionHandlerProvider) {
19-
$exceptionHandlerProvider.mode('log');
20-
}));
21-
2219
beforeEach(inject(function(_$compile_, _$rootScope_) {
2320
$rootScope = _$rootScope_;
2421
$compile = _$compile_;
2522
}));
2623

27-
afterEach(inject(function($exceptionHandler) {
28-
if ($exceptionHandler.errors.length) {
29-
dump(jasmine.getEnv().currentSpec.getFullName());
30-
dump('$exceptionHandler has errors');
31-
dump($exceptionHandler.errors);
32-
expect($exceptionHandler.errors).toBe([]);
33-
}
34-
}));
35-
3624
it('should bind in the current scope the controller of a component', function() {
3725
$rootScope.$ctrl = 'undamaged';
3826

@@ -41,6 +29,12 @@ describe('ngRef', function() {
4129
expect($rootScope.myComponent).toBe(myComponentController);
4230
});
4331

32+
it('should throw if the expression is not assignable', function() {
33+
expect(function() {
34+
$compile('<my-component ng-ref="\'hello\'"></my-component>')($rootScope);
35+
}).toThrowMinErr('ngRef', 'nonassign', 'Expression in ngRef="\'hello\'" is non-assignable!');
36+
});
37+
4438
it('should work with non:normalized entity name', function() {
4539
$compile('<my:component ng-ref="myComponent1"></my:component>')($rootScope);
4640
expect($rootScope.myComponent1).toBe(myComponentController);
@@ -114,15 +108,6 @@ describe('ngRef', function() {
114108
expect($rootScope.$ctrl.myComponent).toBe(myComponentController);
115109
});
116110

117-
it('should bind the element instead of the controller of a component if ngRefElement is set', function() {
118-
$rootScope.$ctrl = 'undamaged';
119-
120-
var el = $compile('<my-component ng-ref="myEl" ng-ref-element></my-component>')($rootScope);
121-
expect($rootScope.$ctrl).toBe('undamaged');
122-
expect($rootScope.myEl).toEqual(el);
123-
expect($rootScope.myEl[0].textContent).toBe('foo');
124-
});
125-
126111
});
127112

128113
it('should bind the jqlite wrapped DOM element if there is no component', inject(function($compile, $rootScope) {
@@ -158,28 +143,112 @@ describe('ngRef', function() {
158143
});
159144
});
160145

146+
describe('ngRefRead', function() {
161147

162-
it('should bind the element instead an element-directive controller if ngRefElement is set', function() {
163-
var myDirectiveController;
148+
it('should bind the element instead of the controller of a component if ngRefRead="$element" is set', function() {
164149

165-
module(function($compileProvider) {
166-
$compileProvider.directive('myDirective', function() {
167-
return {
168-
restrict: 'E',
150+
module(function($compileProvider) {
151+
152+
$compileProvider.component('myComponent', {
169153
template: 'my text',
170-
controller: function() {
171-
myDirectiveController = this;
172-
}
173-
};
154+
controller: function() {}
155+
});
156+
});
157+
158+
inject(function($compile, $rootScope) {
159+
160+
var el = $compile('<my-component ng-ref="myEl" ng-ref-read="$element"></my-component>')($rootScope);
161+
expect($rootScope.myEl).toEqual(el);
162+
expect($rootScope.myEl[0].textContent).toBe('my text');
174163
});
175164
});
176165

177-
inject(function($compile, $rootScope) {
178-
var el = $compile('<my-directive ng-ref="myEl" ng-ref-element></my-directive>')($rootScope);
179166

180-
expect($rootScope.myEl).toEqual(el);
181-
expect($rootScope.myEl[0].textContent).toBe('my text');
167+
it('should bind the element instead an element-directive controller if ngRefRead="$element" is set', function() {
168+
169+
module(function($compileProvider) {
170+
$compileProvider.directive('myDirective', function() {
171+
return {
172+
restrict: 'E',
173+
template: 'my text',
174+
controller: function() {}
175+
};
176+
});
177+
});
178+
179+
inject(function($compile, $rootScope) {
180+
var el = $compile('<my-directive ng-ref="myEl" ng-ref-read="$element"></my-directive>')($rootScope);
181+
182+
expect($rootScope.myEl).toEqual(el);
183+
expect($rootScope.myEl[0].textContent).toBe('my text');
184+
});
185+
});
186+
187+
188+
it('should bind an attribute-directive controller if ngRefRead="controllerName" is set', function() {
189+
var attrDirective2Controller;
190+
191+
module(function($compileProvider) {
192+
$compileProvider.directive('elementDirective', function() {
193+
return {
194+
restrict: 'E',
195+
template: 'my text',
196+
controller: function() {}
197+
};
198+
});
199+
200+
$compileProvider.directive('attributeDirective1', function() {
201+
return {
202+
restrict: 'A',
203+
controller: function() {
204+
attrDirective2Controller = this;
205+
}
206+
};
207+
});
208+
209+
$compileProvider.directive('attributeDirective2', function() {
210+
return {
211+
restrict: 'A',
212+
controller: function() {}
213+
};
214+
});
215+
216+
});
217+
218+
inject(function($compile, $rootScope) {
219+
var el = $compile('<element-directive' +
220+
'attribute-directive-1' +
221+
'attribute-directive-2' +
222+
'ng-ref="myController"' +
223+
'ng-ref-read="$element"></element-directive>')($rootScope);
224+
225+
expect($rootScope.myController).toBe(attrDirective2Controller);
226+
});
182227
});
228+
229+
it('should throw if no controller is found for the ngRefRead value', function() {
230+
231+
module(function($compileProvider) {
232+
$compileProvider.directive('elementDirective', function() {
233+
return {
234+
restrict: 'E',
235+
template: 'my text',
236+
controller: function() {}
237+
};
238+
});
239+
});
240+
241+
inject(function($compile, $rootScope) {
242+
243+
expect(function() {
244+
$compile('<element-directive ' +
245+
'ng-ref="myController"' +
246+
'ng-ref-read="attribute"></element-directive>')($rootScope);
247+
}).toThrowMinErr('ngRef', 'noctrl', 'The controller for ngRefRead="attribute" could not be found on ngRef="myController"');
248+
249+
});
250+
});
251+
183252
});
184253

185254

0 commit comments

Comments
 (0)