3

Guys I have some simple html, for illustration purposes say it looks like this,

<div>{{class.name}}</div>
<div>
    <div>{{class.teacher.name}}</div>
    <div>{{class.teacher.age}}</div>
    <div>{{class.teacher.rating}}</div>
</div>

now the model as you can see has a class object which has a name property and a teacher property. What I would like to do is avoid the duplication in this code so that my bindings look more like this.

<div>{{class.name}}</div>
<div some-directive-here="class.teacher">
    <div>{{name}}</div>
    <div>{{age}}</div>
    <div>{{rating}}</div>
</div>

Does angular support a directive where I can create a new scope for a dom element as shown above? I don't want to use ng-controller as it create a new scope and disconnects me from the original model data.

1
  • AFAIK, there's nothing available out of the box. A new scope doesn't disconnect you from the rest of the data though, unless you create a new isolate scope. Otherwise the new child scope inherits all properties from the parent scope. Commented Feb 4, 2014 at 12:16

2 Answers 2

1

Here is a plunker: http://plnkr.co/edit/MqesLIUA1kq1S7BLal3N?p=preview

A simple directive which creates a new scope and extend it with the evaluated expression of it's parent scope.

Solution:

app.directive('newScope', function($parse){
  return {
    scope:true,
    compile: function (tElm,tAttrs){
      var fn = $parse(tAttrs.newScope);

      return function(scope, elm, attrs){
        var property = fn(scope.$parent);
        property = angular.isObject(property) ? property : {};
        angular.extend(scope, property);
      }      
    } 
  }
})
Sign up to request clarification or add additional context in comments.

8 Comments

This is just what I needed. Little surprised angular doesn't do this out of the box as it makes binding expressions far cleaner. Thanks!
Angular supports custom directives out-of-the-box, you should not care if it's a core or a plugin.
you don't have to read parent scope because with {scope:true} you created new non-isolate scope plnkr.co/edit/RTZdKxRShdsr6fxy2kCo?p=preview
@MatjazLipus It's bad to rely on scope inheritance in this case. See this example: plnkr.co/edit/uJJPDya2DJIE7CaUAPaA?p=preview , all child elements post linking functions could possibly shadow our object.
@llan one thing I did notice with your solution is that functions defined on the scope cannot be accessed with directives such as ng-click. angular.extend only copies properties.
|
0

An addition to the solution is consider async solutions. I have taken the plnkr example and updated the compile function and set the class-property after 2 seconds.

http://plnkr.co/edit/X8y3ArvTD3WDZIIB3qFk?p=preview

app.directive('newScope', function($parse){
  return {
    scope:true,
    compile: function (tElm,tAttrs){
      var init = false;
      var attr = tAttrs.newScope;
      var fn = $parse(attr);

      var linkFunction = function (scope, elm, attrs) {

        if (!init) {
          scope.$watch(attr, function (newValue, oldValue) {
            linkFunction(scope, elm, attrs);
          });
        }

        var property = fn(scope.$parent);
        property = angular.isObject(property) ? property : {};
        angular.extend(scope, property);

        init = true;

      };

      return linkFunction;    
    } 
  }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.