Skip to content

Commit 7573156

Browse files
fix(views): Better validation of view declarations (throw when there are state-level and view-level conflicts)
Closes #3340
1 parent 66103fc commit 7573156

File tree

3 files changed

+17
-12
lines changed

3 files changed

+17
-12
lines changed

src/statebuilders/views.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,20 @@ export function ng1ViewsBuilder(state: StateObject) {
3737
ctrlKeys = ['controller', 'controllerProvider', 'controllerAs', 'resolveAs'],
3838
compKeys = ['component', 'bindings', 'componentProvider'],
3939
nonCompKeys = tplKeys.concat(ctrlKeys),
40-
allKeys = compKeys.concat(nonCompKeys);
40+
allViewKeys = compKeys.concat(nonCompKeys);
41+
42+
// Do not allow a state to have both state-level props and also a `views: {}` property.
43+
// A state without a `views: {}` property can declare properties for the `$default` view as properties of the state.
44+
// However, the `$default` approach should not be mixed with a separate `views: ` block.
45+
if (isDefined(state.views) && hasAnyKey(allViewKeys, state)) {
46+
throw new Error(`State '${state.name}' has a 'views' object. ` +
47+
`It cannot also have "view properties" at the state level. ` +
48+
`Move the following properties into a view (in the 'views' object): ` +
49+
` ${allViewKeys.filter(key => isDefined(state[key])).join(", ")}`);
50+
}
4151

4252
let views: { [key: string]: Ng1ViewDeclaration } = {},
43-
viewsObject = state.views || { "$default": pick(state, allKeys) };
53+
viewsObject = state.views || { "$default": pick(state, allViewKeys) };
4454

4555
forEach(viewsObject, function (config: Ng1ViewDeclaration, name: string) {
4656
// Account for views: { "": { template... } }
@@ -51,6 +61,7 @@ export function ng1ViewsBuilder(state: StateObject) {
5161
// Make a shallow copy of the config object
5262
config = extend({}, config);
5363

64+
// Do not allow a view to mix props for component-style view with props for template/controller-style view
5465
if (hasAnyKey(compKeys, config) && hasAnyKey(nonCompKeys, config)) {
5566
throw new Error(`Cannot combine: ${compKeys.join("|")} with: ${nonCompKeys.join("|")} in stateview: '${name}@${state.name}'`);
5667
}

test/ng1StateBuilderSpec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('Ng1 StateBuilder', function() {
2323
expect(built.$default).toEqualData({ templateUrl: "/foo.html", controller: "FooController", resolveAs: '$resolve' });
2424
});
2525

26-
it('It should use the views object to build views, when defined, function() {
26+
it('It should use the views object to build views, when defined', function() {
2727
var config = { a: { foo: "bar", controller: "FooController" } };
2828
let builtViews = builder.builder('views')({ parent: parent, views: config });
2929
expect(builtViews.a.foo).toEqualData(config.a.foo);

test/viewDirectiveSpec.ts

+3-9
Original file line numberDiff line numberDiff line change
@@ -403,22 +403,16 @@ describe('uiView', function () {
403403
expect(_scope.$ctrl.$resolve.user).toBe('joeschmoe');
404404
}));
405405

406-
it('should use the view-level resolveAs over the state-level resolveAs', inject(function ($state, $q, $timeout) {
406+
it('should not allow both view-level resolveAs and state-level resolveAs on the same state', inject(function ($state, $q, $timeout) {
407407
let views = {
408408
"$default": {
409409
controller: controller,
410410
template: '{{$$$resolve.user}}',
411411
resolveAs: '$$$resolve'
412412
}
413413
};
414-
let state = angular.extend({}, _state, { resolveAs: 'foo', views: views })
415-
$stateProvider.state(state);
416-
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
417-
418-
$state.transitionTo('resolve'); $q.flush(); $timeout.flush();
419-
expect(elem.text()).toBe('joeschmoe');
420-
expect(_scope.$$$resolve).toBeDefined();
421-
expect(_scope.$$$resolve.user).toBe('joeschmoe');
414+
let state = angular.extend({}, _state, { resolveAs: 'foo', views: views });
415+
expect(() => $stateProvider.state(state)).toThrowError(/resolveAs/);
422416
}));
423417
});
424418

0 commit comments

Comments
 (0)