1

Thanks in advance for taking the time to look into this question

I have serverside generated code that renders a directive wrapped around pre-rendered content.

  <serverside-demo color="blue">
  <p><strong>Content from Server, wrapped in a directive.</strong></p>
    <p>I want this color to show: <span ng-style="{color: color}">{{color}}</span></p>
    <button ng-click="onClickButtonInDirective()">Click Me</button>
  </serverside-demo>

This means that 1.) the directive tag, 2.) the content inside the directive tag, 3.)the ng-click and 4.) The curly braces syntax are all generated by the server.

I want AngularJs to pick up the generated code, recompile the template and deal with the scope.

The problem is that I am having trouble getting it working. I understand that because the ng-click is inside the controller block, it is picked up not by the directive isolated scope, but the parent controllers. Instead I want the opposite... to pick up the onClickButtonInDirective scope function inside the serversideDemo link

I have created a jsfiddle best explaining my problem, which aims to clearly demonstrate the working "traditional" way of loading the template separately (which works) comparing it to the server-side way.

https://jsfiddle.net/stevewbrown/beLccjd2/3/

What is the best way to do this?

Thank you!

CarbonDry
  • 850
  • 1
  • 12
  • 25
  • What do you mean by the verb "to pick up"? Are you asking how to communicate an event from inside a component to a parent controller? In that case, the directive should use expression (`&`) binding to invoke a function on the parent scope. – georgeawg Mar 04 '17 at 18:26
  • No, that is the opposite of what I want because that would involve communicating outside of the directive. The goal is to have ng-click call a function inside the directives isolated scope, as illustrated in the jsfiddle – CarbonDry Mar 04 '17 at 18:32
  • The goal is to simply have the content nested inside the directive to have access to the directives scope exactly if we were using template or templateUrl. This is what I mean by pick up. :) – CarbonDry Mar 04 '17 at 18:34
  • Possible duplicate of [Communicating Events from Parent to Child in AngularJS Components](http://stackoverflow.com/questions/37439300/communicating-events-from-parent-to-child-in-angularjs-components) – georgeawg Mar 04 '17 at 18:43
  • @georgeawg I don't think so because there is no parent to child communication (infact in the jsfiddle I have a console log which demonstrates that this is happening incorrectly), the question is about handling the nested markup inside the directive as if it were compiled with template or templateUrl – CarbonDry Mar 04 '17 at 18:59
  • @CarbonDry I suggest you to use ng-template instead of manually compiling your view. https://docs.angularjs.org/api/ng/directive/script take a look at that. – voodoo_patch Dec 10 '18 at 13:32

2 Answers2

1

There are two major problem in your code

1- directive name and dom element not matched, - missing in dom element

app.directive('serverSideDemo', function() {

use <server-side-demo color="blue"> instead of <serverside-demo color="blue">

2- you need to compile the html code of server-side-demo dom with directive scope in link function

$compile(element.contents())(scope);

Working jsfiddle

Gaurav Kumar Singh
  • 1,550
  • 3
  • 11
  • 31
  • Thanks, I think this is what I'm looking for. Will do a bit of checking , and then I'll make as the correct answer. – CarbonDry Mar 04 '17 at 23:21
  • Is there any reason why this is in the link: property and not the compile: property? – CarbonDry Mar 05 '17 at 00:55
  • This is great that the ng-click is linking to the isolate scope, but it's not quite 100% yet. Please see https://jsfiddle.net/beLccjd2/5/ to demonstrate this. If you compare the console logs between the button clicks in each directive you will see that the behaviour is different... The serverside demo is calling both its internal scope AND parent controller scope, whereas the traditional demo is correctly calling only its internal scope. What gives? Thanks for your help so far. (also fixed a typo in your updated jsfiddle `` to `` – CarbonDry Mar 05 '17 at 01:00
  • Updated the jsfiddle again, https://jsfiddle.net/stevewbrown/ntvc3a5q/ . Now we have an added directive that uses transclusion: 'element'. This appears to do what I want, pure replication as if I was using template or templateurl by linking the scope with the template exactly ... but I don't understand when to use $compile or transclude()? Why is it that compile takes the parent scope? – CarbonDry Mar 05 '17 at 01:24
-1

Use templateUrl instead of template to fetch the content of directive from server:

app.directive('serverSideDemo', function() {

  return {
    restrict: 'AE',
    scope: {
      color: '='
    },
    templateUrl: 'link/that/returns/html/content',
    link: function(scope, element, attrs) {
      scope.onClickButtonInDirective = function() {
        console.log('You clicked the button in the serverside demo')
        scope.color = scope.color === 'blue' ? 'red' : 'blue';
      }

    }
  };

});

Have a look at angular docs for more details

  • But the post explains that I can't use templateURL, I even created a jsfiddle showing how templateUrl works, but I am limited by the entire page being generated serverside. Did you check the link? – CarbonDry Mar 04 '17 at 18:12