javascript - Angular Directive Template Update on Data Load -


i have directive data being received via api call. directive works fine, problem arises (i believe) because directive loaded before api call finishes. results in whole shebang not working. instead of expected output, {{user}}.

my directive looks this:

app.directive('mydirective', function() {   return {     restrict: 'a',     require: '^ngmodel',     scope: {       ngmodel: '=',     },     template: '<tbody style="background-color: red;" ng-bind-html="renderhtml(listing_html)"></tbody>',     controller: ['$scope', '$http', '$sce',       function($scope, $http, $sce) {         $scope.listing_html += "<td>{{user.name}}</td>"         $scope.renderhtml = function(html_code) {           return $sce.trustashtml(html_code);         };       }     ],     link: function(scope, ielement, iattrs, ctrl) {       scope.$watch('ngmodel', function(newval) {         // *is* firing after data arrives,         // {{user}} object populated. , `user in ngmodel` doesn't         // run correctly either.         console.log(scope.ngmodel);         scope.listing_html = "<tr ng-repeat='user in ngmodel'><td>{{user}}</td></tr>"       })     }    }; }); 

and html simply

<table my-directive my-options='{"name": "name", "email": "email"}' ng-model='userdata'></table> 

i've created plunker ton of comments explain issue.

this question very similar this one, key distinction of solution not working. adding ng-cloak mine makes not display. may worth noting i've been using this reference on way construct directive.

i not 100% sure, believe ngbindhtml not in case.
ngbindhtml displaying "normal" html, want display angular, magic html.
need $compile html angular-aware , link compiled html scope.

i used following approach (with apparently results):

controller: function ($scope, $element, $compile) {   var html = createtmpl(angular.fromjson($scope.myoptions));   $scope.$watch('ngmodel', function (newval) {       var elem      = angular.element(html);   // creating element       var linkingfn = $compile(elem);          // compiling element       linkingfn($scope);                       // linking element       $element.html('');                       // removing previous content       $element.append(elem);                   // inserting new content        // above purposedly explicit highlight        // going on. it's moe concise equivalent be:       //$element.html('').append($compile(html)($scope));   }); 

where createtmpl() defined take account myoptions , return appropriate template creating table header-row (based on keys of myoptions) , data-rows properties defined myoptions's values:

function createtmpl(options) {     // construct header-row     var html = '<tr>';     angular.foreach(options, function (value, key) {         html += '<th>' + key + '</th>';     });     html += '</tr>\n';      // construct data-rows     html += '<tr ng-repeat="user in ngmodel">';     angular.foreach(options, function (value, key) {         html += '<td>{{user' + value + '}}</td>';     });     html += '</tr>\n';      // return template     return html; } 

see, also, short demo.
of course, demonstration purposes , not handle production-ready app should (e.g. accounting errors, missing properties, changes in myoptions , whatnot).


update:

i had strong competion, did slight modification of code above in order support nested properties. e.g. given object following structure:

user = {     name: 'expertsystem',     company: {         name: 'expertsystem s.a.',         ranking: 100     } }; 

we can have company name displayed in column of our table, defining myoptions this:

myoptions='{"company name": "company.name"} 

Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -