Answers.Body: <p>I've been recently digging into Angularjs, as I'm trying to make some customization, and this is what I figured out after a reading loads of blog posts covering the subject. I'm not an angular expert so I don't know how this affects performance.</p>
  
  <p>The following script is from an extension using <a href="https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules?desktop=true" rel="noreferrer">hook_civicrm_angularModules</a> and Angular's <code>$provide</code> service in conjunction with the <code>decorator</code> function to intercept a CiviCRM directive and 'decorate' it to add/replace/extend behaviour, more info <a href="https://docs.angularjs.org/api/auto/service/provide#decorator" rel="noreferrer">here</a>.</p>
  
  <p><strong>Demonstration</strong>:</p>
  
  <pre><code>// myModule.js  
    (function(angular, $, _) {
        // declare your module
        angular.module('myModule', []);
  
        // Hook into crmMailing module
        angular.module('crmMailing').config(function($provide){
           // intercept crmMailingBlockMailing directive, note the 'Directive' suffix
           $provide.decorator('crmMailingBlockMailingDirective', function($delegate){
                var directive = $delegate[0];
  
                // Original compile function
                var compile = directive.compile;
                // New compile function
                directive.compile = function(Element, Attrs){
                    var link = compile.apply(this, arguments);
                    // Append your custom directive
                    Element.append('&lt;div crm-my-directive&gt;&lt;/div&gt;');
                    return function(scope, elem, attrs){
                        link.apply(this, arguments);
                    };
                };
                return $delegate;
           });
        });
  
        /*
        * Extending crmMailing
        */
  
        // Your simple custom directive
        angular.module('crmMailing').directive('crmMyDirective', function(){
           return {templateUrl: CRM.resourceUrls['uk.co.myextension'] + '/ang/directives/crmMyDirective.html',
                  controller: 'ExampleCtrl',
           };
        });
  
        // Your controller
        angular.module('crmMailing').controller('ExampleCtrl', function($scope, crmMsgTemplates){
          $scope.$watchCollection('mailing', function(mailing){
              crmMsgTemplates.get(mailing.msg_template_id)
              .then(function(value){
                   mailing.msg_template_title = value.msg_title;
              });
          });
        });
  
      })(angular, CRM.$, CRM._);
  </code></pre>
  
  <p><strong>Custom directive template</strong></p>
  
  <pre><code>&lt;div id="my-directive"&gt;
      &lt;div crm-ui-accordion="{title: ts('My Custom Directive')}"&gt;
          &lt;p&gt;Template Id: {{mailing.msg_template_id}} | Template Title: {{mailing.msg_template_title}}&lt;/p&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p><a href="https://i.sstatic.net/n4q7S.png" rel="noreferrer"><img src="https://i.sstatic.net/n4q7S.png" alt="enter image description here"></a></p>
  
  <p>You can pretty much create your own services/factories, directives, etc or change the behavior of existing ones and hook it into the Mailing app.</p>
  
  <p>Hope it helps.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-27T20:10:21.053Z
Answers.Text: Thanks for sharing this! It looks like a pretty thorough example and lines up with ideas from Angular upstream. (For reference, there are some relevant docs like [$provide](https://code.angularjs.org/1.2.16/docs/api/auto/object/$provide), but they're pretty thin. This answer seems more comprehensive.)
Answers.UserDisplayName: Tim Otten
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-26T15:37:27.070Z
Answers.LastActivityDate: 2016-05-30T11:10:28.973Z
Answers.LastEditDate: 2016-05-30T11:10:28.973Z
Answers.UserDisplayName: Andrei
Body: <p>I have developed an extension which adds the possibility to add attachments to a message template. When a user select the template in CiviMail the linked attachments are also sent. This is working well.</p>
  
  <p>But now I want to show which attachments are linked to a template when a user selects a template in the CiviMail UI.</p>
  
  <p>In the old way I would add jQuery and an event listener to the drop down with templates and then fetch with Ajax the linked attachments and inject them somewhere in the screen. However CiviMail is now working with Angular and my understanding is that this should be much and much easier in Angular. However I have played around and can't get it working.</p>
  
  <p>My question is how do I use angular to listen for a template change and then inject some data into the angular template?</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-15T22:42:40.633Z
Comments.Text: Not an answer, just a note, you can access the angular scope with javascript as angular is already in the page, create/edit new/existing mailing and try this in the browser console: `var scope = angular.element('[ng-controller="MsgTemplateCtrl"]').scope(); scope.$watch('mailing.msg_template_id', function(){
   console.log(scope.mailing.msg_template_id);
  });` with __scope.mailing__ you can access and listen to the mailing params, I guess you already know it but if you enable debug and add `?angularDebug` at the end of the url you will see a new accordion with the params, hope that helps somehow
Comments.UserDisplayName: Andrei
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-16T10:57:57.670Z
Comments.Text: Thanks Andrei. However it does not work because the element the scope() function is not available during execution of my script.
Comments.UserDisplayName: Jaap Jansma - CiviCooP
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-16T12:12:05.037Z
Comments.Text: how do you inject the script? I just tried it myself, and indeed it failed but enclosing the mentioned javascript in a function and delaying the function with `setTimeout()` it does work as expected, the mailing page always takes a 2-4 seconds to completely load all the elements in my case
Comments.UserDisplayName: Andrei
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-16T12:17:58.523Z
Comments.Text: Yes I have discovered that with a setTimeout it is working but I don't think setTimeout is reliable because on my computer it could be 2-3 seconds on another one it could 4-5 seconds before the page is ready.  My script is injected with the angularModules hook from civicrm
Comments.UserDisplayName: Jaap Jansma - CiviCooP
Tags: <civimail><angular>
Title: Adding dynamic data in CiviMail angular template
ThreadText: # Adding dynamic data in CiviMail angular template
  
  (Asked by: username_0 on 2016-03-14)
  
  I have developed an extension which adds the possibility to add attachments to a message template. When a user select the template in CiviMail the linked attachments are also sent. This is working well.
  
  But now I want to show which attachments are linked to a template when a user selects a template in the CiviMail UI.
  
  In the old way I would add jQuery and an event listener to the drop down with templates and then fetch with Ajax the linked attachments and inject them somewhere in the screen. However CiviMail is now working with Angular and my understanding is that this should be much and much easier in Angular. However I have played around and can't get it working.
  
  My question is how do I use angular to listen for a template change and then inject some data into the angular template?
  
  **Tags:** civimail, angular
  
  > **Comments:**
  > **username_1**: Not an answer, just a note, you can access the angular scope with javascript as angular is already in the page, create/edit new/existing mailing and try this in the browser console: `var scope = angular.element('[ng-controller="MsgTemplateCtrl"]').scope(); scope.$watch('mailing.msg_template_id', function(){  console.log(scope.mailing.msg_template_id); });` with __scope.mailing__ you can access and listen to the mailing params, I guess you already know it but if you enable debug and add `?angularDebug` at the end of the url you will see a new accordion with the params, hope that helps somehow  
  > **username_0**: Thanks username_1. However it does not work because the element the scope() function is not available during execution of my script.  
  > **username_1**: how do you inject the script? I just tried it myself, and indeed it failed but enclosing the mentioned javascript in a function and delaying the function with `setTimeout()` it does work as expected, the mailing page always takes a 2-4 seconds to completely load all the elements in my case  
  > **username_0**: Yes I have discovered that with a setTimeout it is working but I don't think setTimeout is reliable because on my computer it could be 2-3 seconds on another one it could 4-5 seconds before the page is ready.  My script is injected with the angularModules hook from civicrm  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2016-05-26. Score: 7 | Accepted answer
  
  I've been recently digging into Angularjs, as I'm trying to make some customization, and this is what I figured out after a reading loads of blog posts covering the subject. I'm not an angular expert so I don't know how this affects performance.
  
  The following script is from an extension using [hook\_civicrm\_angularModules](https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules?desktop=true) and Angular's `$provide` service in conjunction with the `decorator` function to intercept a CiviCRM directive and 'decorate' it to add/replace/extend behaviour, more info [here](https://docs.angularjs.org/api/auto/service/provide#decorator).
  
  **Demonstration**:
  
  ```
  // myModule.js  
    (function(angular, $, _) {
        // declare your module
        angular.module('myModule', []);
  
        // Hook into crmMailing module
        angular.module('crmMailing').config(function($provide){
           // intercept crmMailingBlockMailing directive, note the 'Directive' suffix
           $provide.decorator('crmMailingBlockMailingDirective', function($delegate){
                var directive = $delegate[0];
  
                // Original compile function
                var compile = directive.compile;
                // New compile function
                directive.compile = function(Element, Attrs){
                    var link = compile.apply(this, arguments);
                    // Append your custom directive
                    Element.append('<div crm-my-directive></div>');
                    return function(scope, elem, attrs){
                        link.apply(this, arguments);
                    };
                };
                return $delegate;
           });
        });
  
        /*
        * Extending crmMailing
        */
  
        // Your simple custom directive
        angular.module('crmMailing').directive('crmMyDirective', function(){
           return {templateUrl: CRM.resourceUrls['uk.co.myextension'] + '/ang/directives/crmMyDirective.html',
                  controller: 'ExampleCtrl',
           };
        });
  
        // Your controller
        angular.module('crmMailing').controller('ExampleCtrl', function($scope, crmMsgTemplates){
          $scope.$watchCollection('mailing', function(mailing){
              crmMsgTemplates.get(mailing.msg_template_id)
              .then(function(value){
                   mailing.msg_template_title = value.msg_title;
              });
          });
        });
  
      })(angular, CRM.$, CRM._);
  
  ```
  
  **Custom directive template**
  
  ```
  <div id="my-directive">
      <div crm-ui-accordion="{title: ts('My Custom Directive')}">
          <p>Template Id: {{mailing.msg_template_id}} | Template Title: {{mailing.msg_template_title}}</p>
      </div>
  </div>
  
  ```
  
  [![enter image description here](https://i.sstatic.net/n4q7S.png)](https://i.sstatic.net/n4q7S.png)
  
  You can pretty much create your own services/factories, directives, etc or change the behavior of existing ones and hook it into the Mailing app.
  
  Hope it helps.
  
  > **Comments:**
  > **username_2**: Thanks for sharing this! It looks like a pretty thorough example and lines up with ideas from Angular upstream. (For reference, there are some relevant docs like [$provide](https://code.angularjs.org/1.2.16/docs/api/auto/object/$provide), but they're pretty thin. This answer seems more comprehensive.)  
  
  ---
  
  