Skip to content

Use Deep merge rather then extend when Inheriting Data Properties on Nested views #3045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
martyzz1 opened this issue Sep 27, 2016 · 5 comments

Comments

@martyzz1
Copy link

// inherit 'data' from parent and override by own values (if any)
      data: function(state) {
        if (state.parent && state.parent.data) {
          state.data = state.self.data = angular.merge(state.parent.data, state.data);
        }
        return state.data;
      },

This seems to work for me ok, would really help when using Data to provide configurable properties for things like Meta data

@christopherthielen
Copy link
Contributor

We used to do angular.extend(), but now we use prototypal inheritance. We do this so parent states can update their data, and child states will automatically get up-to-date parent data.

For this reason, I don't think we can switch back to the "copy" approach.

I'm curious what problems you're experiencing with the current prototypal inherit approach?

@martyzz1
Copy link
Author

sure. given this code

.state(
'services', {
    abstract: true,
    url: '/services',
    templateUrl: '/services/base.html',
    controller: 'servicesCtrl',
    data: {
        'meta': {
            'og:image': 'http://www.yourdomain.com/img/facebookimage.jpg',
            'author': 'Author'
        }
    }
}

.state(
'services.vaccinations', {
    url: '/vaccinations',
    templateUrl: '/services/vaccinations.html',
    controller: '',
    data: {
        'meta': {
            'title': 'Vaccinations - All You Need To Know',
            'og:title': 'All You Need To Know About Vaccinations',
            'og:description': 'Useful information about Routine Vaccines and Boosters',
        }
    }
}

In /services/vaccinations I would expect $state.current.data.meta to be

'meta': {
    'og:image': 'http://www.yourdomain.com/img/facebookimage.jpg',
    'author': 'Author',
    'title': 'Vaccinations - All You Need To Know',
    'og:title': 'All You Need To Know About Vaccinations',
    'og:description': 'Useful information about Routine Vaccines and Boosters',

}

But it turns out to be

'meta': {
            'title': 'Vaccinations - All You Need To Know',
            'og:title': 'All You Need To Know About Vaccinations',
            'og:description': 'Useful information about Routine Vaccines and Boosters',
        }

@martyzz1
Copy link
Author

btw... I'm getting around the problem by doing this

$rootScope.$on('$stateChangeSuccess', function(event, toState) {
              var $state = $injector.get('$state');
              var stateParent = $state.get('^');
              if ( stateParent) {
                if (stateParent.data && stateParent.data.meta) {
                  toState.data.meta = angular.merge(stateParent.data.meta, toState.data.meta);
                }
              }

              return update(event, toState);
            });

I'm kinda assuming that this will only work with inheritence from the root view to the leaf view - and won't include anything inbetween.

@christopherthielen
Copy link
Contributor

christopherthielen commented Sep 27, 2016

The ship has sailed on the decision between copying vs prototypal inheritance. Switching to deep copy would be a breaking change for many apps which expect a child state's data property to clobber a parent state's data property.

If you want non-standard (deep copy) behavior you can certainly implement it for your app:

  $stateProvider.decorator('data', function(state, parentDecoratorFn) {
    var parentData = state.parent && state.parent.data || {};
    var selfData = state.self.data || {};
    return state.self.data = angular.merge({}, parentData, selfData);
  });

example:
http://plnkr.co/edit/Wm9p13QRkxCjRKOwVvbQ?p=preview

@martyzz1
Copy link
Author

no worries, thanks for the example, thats really nice of you.. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants