0

I tried to follow this youtube tutorial by John Lindquist where he explains directives by categorizing them into components and containers.
So I tried to do so, to have a container (slide) that will hold different items (textarea, images, videos ...) but my example is more dynamic.
His example was something like this:

<panel title="{{title}}">
  <element text="{{body}}"></element>
</panel>

But mine is more like this:

<slide ng-repeat="slide in slides" slide-id="{{slide.id}}">
  <component
    element="component"
    type="{{component.type}}"
    ng-repeat="component in slide.components"
  >
  </component>
</slide>

And that's not everything the component directive (that was taken from this SO question) is a directive that will take the type and change the template to the correct directive e.g if editor change this:

<component
  element="component"
  type="{{component.type}}"
  ng-repeat="component in slide.components"
>
</component>

To this:

<component
  element="component"
  editor
  ng-repeat="component in slide.components"
>
</component>

And then the editor directive will do its work by changing the last template to this:

<div
  contenteditable="true"
  class="editor text-content"
>
  {{element.content.text}}
</div>

But I don't know why it's not working the component directive doesn't get executed at all, I think there's something wrong with the isolated scope maybe I miss understood something.
Working example in Plunker.

Update:

Thanks for Marco Alves for pointing the missing restrict to me, I don't remember if I write the example initially with a link function or a compile function but it should be with a compile function because the solution with a link function may appears to be working but after opening the console a weird error appears (at least weird for me):

Error: InvalidCharacterError: DOM Exception 5
Error: An invalid or illegal character was specified, such as in an XML name.
at x.extend.attr(jquery.min.js:5:4051)
at Function.x.extend.access(jquery.min.js:4:5847)
at x.fn.extend.attr (jquery.min.js:5:715)
at link (component-directive.js:7:11)
at nodeLinkFn (angular.js:4774:13)
at angular.js:4914:15
at nodeLinkFn (angular.js:4768:24)
at angular.js:4913:13
at angular.js:9782:11
at wrappedCallback (angular.js:7303:59) <div contenteditable="true" class="ng-scope editor text-content ng-binding" element="component" type="" ng-repeat="component in slide.components" editor=""> angular.js:6173
(anonymous function) angular.js:6173
(anonymous function) angular.js:5219
nodeLinkFn angular.js:4777
(anonymous function) angular.js:4914
nodeLinkFn angular.js:4768
(anonymous function) angular.js:4913
(anonymous function) angular.js:9782
wrappedCallback angular.js:7303
wrappedCallback angular.js:7303
(anonymous function) angular.js:7340
Scope.$eval angular.js:8685
Scope.$digest angular.js:8548
Scope.$apply angular.js:8771
done angular.js:10004
completeRequest angular.js:10180
xhr.onreadystatechange

Check this answer from from Marco Alves.
So the component directive is like this:

app.directive('component', ['$compile', function($compile){
  return {
    restrict: "E",
    compile:function(tElement, tAttrs){
      var el = tElement[0];
      if(el.getAttribute('type')){
        el.removeAttribute('type');
        el.setAttribute(tAttrs.type,'');
        return function(scope){
          $compile(el)(scope);
        };
      }
    }
  };
}]);

The problem with this is that the component directives still doesn't get compiled, even though it works fine in this plunker example.
Any help, thanks in advance.

Community
  • 1
  • 1
Yahya KACEM
  • 2,481
  • 7
  • 34
  • 61

1 Answers1

1

For starters, you forgot to set the restrict property on the component directive to E... That's why it doesn't get compiled.

Edit 1 :

Got it to render the component directive but still has additional errors.

Take a look: http://plnkr.co/edit/ENkWIVUnHubxydWgB4pU?p=preview

Edit 2:

I think I solved it. http://plnkr.co/edit/ENkWIVUnHubxydWgB4pU?p=preview

I changed:

  • Removed the 'E' attribute in the component directive definition
  • Use removeAttr inside the componente directive linker to remove both the type and component attributes
  • Changed the index.html to use the component directive as an attribute instead of an element
marco alves
  • 1,707
  • 2
  • 18
  • 28
  • Actually it was working with your first answer this one seems to have an additional removeAttr for the component because when it's restricted as element it will be converted automatically so no need for the removeAttr('component'), here's a [plunker with working code](http://plnkr.co/edit/z9BDVTX5GtRqS0H3XJJr?p=preview), but is it slow a little bit, thanks for the help. – Yahya KACEM Apr 25 '13 at 17:43
  • Sorry, I had a typo in it check it now. – Yahya KACEM Apr 25 '13 at 17:48
  • 1
    Ok, but without you run the compiler a few more times: both when the component directive has the type attribute and without it. With my previous approach you just compile the component directive one time for each time it appears in the dom. See here[http://plnkr.co/edit/HoOoZSEGhJ2AK2nKHStO?p=preview] for more. – marco alves Apr 25 '13 at 18:43