0

I am trying to make a dynamic framework with angularjs. I load sections with a webapi, that have data about the directive that it uses and the data that should be used in that directive. The data that I send can look like this:

[
    {
        id: "section1",
        directive: "<my-directive></my-directive>",
        content: {
            title: "This is a title",
            text: "This is a text"
        }
    },
    {
        id: "section2",
        directive: "<my-other></my-other>",
        content: {
            title: "This is another title",
            list: ["This is a text", "This is another text"]
        }
    }
]

When I load this data, I convert the directives in to element with $compile.

angular.forEach($sections, (value, key):void => {
    value.directive = $compile(value.directive)($scope);
}

So I can actually load this data in the view, like this:

<div ng-repeat="section in sections">
    {{section.directive}}
</div>

First of all, this doesn't show up in my view, so how do I fix this? Then the second issue I have. When I actually get this directive loaded into the view, how will I be able to access the data that should be used in this directive? I do have an id added to the sections.This is what I tried:

angular.forEach($sections, (value, key):void => {
    value.directive = $compile(value.directive)($scope);
    var parent = angular.element('#sectionsparent'); //The parent element has this id
    parent.append(value.directive);
}

This way the section elements show up, but I cannot access the data that should be loaded inside the directive.

Thank you for your help in advance, let me know if you need more information.

EDIT:

When the directive is eventually loaded, I want to be able to access the data that belongs to that section. So if we take first section in the sample data, I want to be able to do the following in the template of the directive:

<!-- This file is myDirectiveTemplate.hmtl -->
<div id="{{id}}>
    <h1>{{title}}</h1>
    <p>{{text}}</p>
</div>

I don't care if I have to access these properties through a viewmodel object, so it would be {{vm.id}} instead of {{id}}. But I prefer to not have any function calls inside my template to actually get data.

2
  • Can you further explain what you mean by "I cannot access the data that should be loaded inside the directive?" Commented Mar 30, 2017 at 2:08
  • I have add the explanation, I hope this helps you @rgthree Commented Mar 30, 2017 at 2:28

1 Answer 1

1

Alright. There may be another way to accomplish this, or perhaps using includes instead of directives, but here's one way at least.

Taking your example code, you can follow your second route with $compile and append but you also need to pass an html-attribute for the isolate scope's content and bind it with a new $scope with the section added. (You also need to wrap in a $timeout so querying the DOM happens after it's initially rendered).

var app = angular.module('app', []);
app.controller('AppCtrl', function($scope, $compile, $timeout) {  
  $scope.sections = [
      {
          id: "section1",
          directive: "my-directive",
          content: {
              title: "This is a title",
              text: "This is a text"
          }
      },
      {
          id: "section2",
          directive: "my-other",
          content: {
              title: "This is another title",
              list: ["This is a text", "This is another text"]
          }
      }
  ];
  
  // Need to timeout so rendering occurs and we can query the DOM.  
  $timeout(() => {
    angular.forEach($scope.sections, (section) => {
      let newScope = $scope.$new();
      newScope.content = section.content;
      let dir = section.directive;
      let compiled = $compile(`<${dir} content="content"></${dir}>`)(newScope);
      let parent = angular.element(document.querySelector('#' + section.id));
      parent.append(compiled);
    });
  });
});

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {content: '='},
    template: `<div>
        <h1>{{content.title}}</h1>
        <p>{{content.text}}</p>
      </div>`,
  };
});

app.directive('myOther', function() {
  return {
    restrict: 'E',
    scope: {content: '='},
    template: `<div>
        <h1>{{content.title}}</h1>
        <ul>
          <li ng-repeat="item in content.list">{{item}}</li>
        </ul>
      </div>`,
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app" ng-controller="AppCtrl">
  <div ng-repeat="section in sections" id="{{section.id}}"></div>
</div>

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.