0

How to attach arbitrary data to an html element declaratively, and retrieve it.

Please see the code. http://plnkr.co/edit/sePv7Y?p=preview

Angular has the jQuery data() support.

So, I want to attach data to each li element (say _data = node ) in the template, and later on to retrieve it using

var li = elm[0]....
console.log('li-', li.data('_data'))
li - {id:1}

Code:

'use strict';

var app = angular.module('Directives', []);

app.controller('MainCtrl', function ($scope) {
   $scope.data = [
                    {id:1}, {id:2}, {id:3}

        ];
});


app.directive('test', function ($timeout) {
  return {
      template: '<li class="ch" ng-repeat="node in data">' +
                '<span class="span2">' + 'id - {{node.id}}' + '</span>' +
                '</li>',
            restrict: 'A',
            link: function (scope, elm, attrs) {
                console.log(elm[0].children);
            }
    };
});

Edit:

Updated the code with how I like to set data.

 template: '<li class="ch" ng-repeat="node in data"  data-node="node">' +

couldn't select the li element properly now to see whether it is working tried,

elm[0].children[0].data()
elm.children[0].data()
etc..
4
  • You code doesn't have anything to do with data(); so is it safe to assume you haven't tried anything yet? Commented Sep 17, 2013 at 12:21
  • I tried, but not sure what is the syntax of setting data declaratively. I just saw a section in jquery doc about html5 data attribute and jquery pulls it in. I am trying to work it out Commented Sep 17, 2013 at 12:23
  • Have you got jQuery included? Commented Sep 17, 2013 at 12:25
  • no, but angular supports data() through its own implementation jqLite Commented Sep 17, 2013 at 12:26

1 Answer 1

2

First of all, if it were some third party lib that you are trying to integrate with angular, that might be ok, but now you're generating DOM with angular and embedding data in the DOM. This is very strange.

Second, your test directive template uses ngRepeat, which creates isolate scope and you won't be able to access li items declaratively. You will have to use DOM traversal, which is also not very angular-way-ish.

Third, your view should be bound to model by angulars two-way bindings. Do not try to simulate opposite behaviour on top of that. Either you should not use angular or you should change your approach to your problem, because it will be pain to develop and maintain otherwise.

I would provide a real answer if you could describe what are you trying to achieve and why exactly do you need that model in data. Now the easiest solution would be ditching test directive and rewriting it as such:

controller's template:

<ul>
  <li ng-repeat="node in data" model-in-data="node">
    <span class="span2">id - {{node.id}}</span>
  </li>
</ul>

directive modelInData

.directive('modelInData', function($parse) {
   return {
     restrict: 'A',
     link: function($scope, $element, $attrs) {
       var model = $parse($attrs.modelInData)($scope);
       $attrs.$set('data', model);
     }
   }
});

Here each li element adds it's model to the data attribute.

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

2 Comments

thanks for the detailed answer and explanation. You are right, I was trying to incorporate a 3rd party drag and drop plugin, and needed a way to attach some data to the dom element. This is to track where it came from, etc. I will look into your code. thanks again
While it is not easy to work with drag and drop libraries, such as jQuery's draggable, sortable etc., it's certainly possible to write more or less every interaction declaratively. Just keep in mind that your model should have defined those interactive properties (position, index, list parent, etc). Any action or callback from third party library should update angular's model, (not the DOM!) and then the view should be rerendered by angular according to updates.

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.