angularjs - Extracting Data from Child Elements and Using it in Directive -


i'm trying create generic directive want use display flexible, spreadsheet-like data entry form.

i'd put data structure & formatting information in html code , have directive take , store in scope later use.

here's sample html i'd use (the information in "field" elements i'd scope):

<array title="breakdown" data="data.breakdown">   <field type="text" default="" name="descr">description</field>   <field type="number" default="0" name="price">price</field>   <field type="number" default="0" name="tax">tax</field> </array> 

and directive far

.directive('array', function(){   return {     restrict: "e",     replace: true,     transclude: true,     templateurl: "js/array-template.html",     compile: function(telement, tattrs, transclude) {       var x=transclude(telement);                      return function(scope, element, attrs) {  //the linking function        scope.title=attrs.title;        }     }   } } 

the variable x gives me array of html elements has not "field" elements bunch of empty "span" elements too. work if needed suspect there's simpler way it.

i found solution!

first i've use last example on angularjs website main page: http://angular.github.io/angularjs.org/#/list start rendered html code contained junk because had use ng-transclude directive have <field> elements processed too.

so looked further , found examples of dynamically created templating. gives lot more flexibility , complete rewrite of html without old piece showing in resulting code.

i had use different method of communicating between directives because method used in angularjs website (shared controller) broke down when no ng-transclude used in main directive's template. used added property module object, since both directives belong same object.

here's full code of solution. hope useful people.

html:

<!doctype html> <html>     <head>         <title></title>         <meta http-equiv="content-type" content="text/html; charset=utf-8">     </head>     <body ng-app="flexlist">         <array title="breakdown" data="record">             <field type="text" default="" name="descr" title="description"></field>             <field type="number" default="0" name="price" title="price"></field>             <field type="number" default="0" name="tax" title="tax"></field>         </array>         <array title="test" data="record">             <field type="text" default="" name="descr" title="description"></field>         </array>      </body>     <script src="js/angular.js"></script>     <script src="js/controller.js"></script> </html> 

javascript ample comments ;-)

function record(){  //a simple constructor provide data table     return [{           descr: "example",           price: 10,           tax: 0.07       },       {           descr: "something else",           price: 15,           tax: 0.11        }   ];   }  var mod=angular.module('flexlist', []); mod.fields=[];  //container shared between directives //the directive <array> mod.directive('array', function($compile){  //injecting $compile service     return {         restrict: 'e',  //restricted element         replace: true,         scope:{             title: '@title'  //getting title attribute scope         },         link: function(scope,element,attr){             //calling function specified in "data" attribute              //which should return data filled table             scope.source=window[attr.data]();               scope.fields=[];  //preparing "field" variable in scope             //copying data collected <field> elements scope             angular.copy(mod.fields,scope.fields);                //preparing collection next use              //(in case more 1 <array> block in page             mod.fields=[];              newcont=angular.element(   //creating template's html '<fieldset>'+     '<legend>{{title}}</legend>'+     '<table border=1>'+         '<tr>'+             '<th ng-repeat="fld in fields">{{fld.title}}</th>'+         '</tr>'+         '<tr ng-repeat="line in source">'+             '<td ng-repeat="fld in fields">{{line[fld.name]}}</td>'+         '</tr>'+     '</table>'+ '</fieldset>');             //applying angular "magic" -- directives in template             $compile(newcont)(scope);               element.replacewith(newcont);  //replace whole <array> element         },         controller: function($scope, $attrs){             // nothing here yet         }     }; });  mod.directive('field',function(){     return {         require: '^array',  //the "^" means <field> has inside <array>         restrict: 'e',  //restricted element         link: function(scope,element,attrs){ //collecting data element            mod.fields.push({  //pushing data collection object                type: attrs.type,                'default': attrs['default'],                name: attrs.name,                title: attrs.title                             });         }     }; }); 

Comments