1

I have a directive which needs to display data from an object in a controller. The piece of data that must be displayed is determined by an attribute of the directive and some other calculations based on other dom elements.

Here is a simplified example.

I have this data:

app.controller('EditorCtrl', function($scope) {
    $scope.blocks = {
        header: 'text1',
        body: 'text2',  
    };
});

And I want it to be displayed with this directive:

app.directive('editable', function() {
    return {
        template: 'data: {{val}}',
        link: function(scope, element, attrs) {
            element.wrap('<div class="editable"></div>');
            data = scope.blocks[attrs.editable];
            val = data;
        }
    }
});

And in HTML:

<h1 editable="header">text1 should be displayed here</h1>
<h1 editable="body">text2 should be displayed here</h1>

How can I accomplish this ? Am I approaching the problem in a right way ?

1
  • This looks ok at first glace - can you create a plunker to see if you recreate it? Commented May 13, 2013 at 15:32

1 Answer 1

3

The 'data: {{val}}' instruction in the directive is expecting "val" to be defined in the scope (and it isnt).

You can create a local scope with "scope:true" to hold the val variable. (see http://docs.angularjs.org/guide/directive scope section).

Something like this would work:

app.directive('editable', function() {
    return {
        template: 'data: {{val}}',
        scope: true,
        link: function(scope, element, attrs) {
            element.wrap('<div class="editable"></div>');
            data = scope.blocks[attrs.editable];
            scope.val = data;
        }
    }
});

In AngularJS, a child scope prototypically inherits from its parent scope, so even though you are creating a new scope, you can still access the blocks object.

Having said that, the previous solution would make it hard for changes in the parent blocks object to be instantly reflected in the DOM h1 nodes. I would instead, do something like this:

<div ng-app="app" ng-controller="EditorCtrl">
   <h1 editable="blocks.header">text1 should be displayed here</h1>
   <h1 editable="blocks.body">text2 should be displayed here</h1>
</div>

And JS:

angular.module('app', []).controller('EditorCtrl', function($scope) {
  $scope.blocks = {
    header: 'text1',
    body: 'text2',  
  };


}).directive('editable', function() {
  return {
    template: 'data: {{text}}',
    scope: {
        'text': '=editable'   
    },
    link: function(scope, element, attrs) {
        element.wrap('<div class="editable"></div>');
    }
  }
});

With the 'text': '=editable' scope declaration you are setting up a bi-directional binding between the local scope text variable and parent "blocks.header/body" (the content of the editable DOM attribute). Any change in blocks variable will be automatically reflected in the DOM.

Sign up to request clarification or add additional context in comments.

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.