Answers.Body: <p>Ok, sorted it out with some suggestions and examples.</p>
  <blockquote>
  <p>$loader = new \Civi\Angular\AngularLoader();
  $loader-&gt;setModules(array('trialadmin'));
  $loader-&gt;setPageName('Administration');
  $loader-&gt;useApp(['activeRoute' =&gt; '/trialadmin/trialdetails']);
  $loader-&gt;load();</p>
  </blockquote>
  <p>Worked with this, but I also used the trace and debug in the browser to determine there likely was another issue with the form actually loading.  Regardless, I've been able to sort it out.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-25T01:24:09.733Z
Answers.LastActivityDate: 2021-05-25T01:24:09.733Z
Answers.UserDisplayName: Norm Dressler
Answers.Body: <p>You are trying to inject an angular snippet into an otherwise non-angular page, and you're wanting to place it into a new tab in the Manage Events page. This is doable but there are a few things to understand:</p>
  <ol>
  <li>Yours might not be the only Angular snippet on the page. Other extensions may want to add them in the future.</li>
  <li>Angular routing requires control of the URL, which your snippet shouldn't assume it has, so I don't recommend using <code>crmApp</code> or <code>ng-route</code>.</li>
  <li>Tab content loads via ajax by default, but it's also possible to pre-load it by supplying a &quot;template&quot; property. This makes Angular stuff simpler.</li>
  </ol>
  <p>I recently faced these same challenges while adding this feature to the new Form Builder (Afform) extension, and ended up improving the way AngularJS loads in Civi. It's available in version 5.37+ and I highly recommend you start using this new service:</p>
  <p>In your hook you'd do this:</p>
  <pre><code>function my_hook_civicrm_tabset($tabsetName, &amp;$tabs, $context) {
    //check if the tab set is Event manage
    if ($tabsetName == 'civicrm/event/manage') {
      if (!empty($context['event_id'])) {
        // Add our Angular module to the page
        Civi::service('angularjs.loader')-&gt;addModules(['trialadmin']);
        // Add the tab
        $tab['Administration'] = [
          'title' =&gt; &quot;Administration&quot;,
          'template' =&gt; 'path/to/your/template.tpl',
          'valid' =&gt; 1,
          'active' =&gt; 1,
          'current' =&gt; false,
        ];
      }
    }
  }
  </code></pre>
  <p>Note that I didn't supply a URL but instead gave a <code>'template'</code> which will cause the tab content to load immediately. So now you've got your module loaded and don't have to worry about ajax for the tab content.</p>
  <p>In your tpl file you need to initialize your Angular module. This will look a little different than the docs which use <code>crmApp</code> and <code>ng-route</code>. It's actually going to be a lot simpler. All you do is add a tag which tells Civi to boostrap Angular and load your module, then just have your module do it's thing.</p>
  <p>So skip all the stuff about routes and controllers. Best practice is to just define a module and a component.</p>
  <p>E.g.</p>
  <pre><code>(function(angular, $, _) {
    angular.module('mymodule', CRM.angRequires('mymodule'));
  
    angular.module('mymodule').component('myComponent' {
      // do your thing
    });
  })(angular, CRM.$, CRM._);
  </code></pre>
  <p>Then your .tpl file would look like this:</p>
  <pre><code>&lt;crm-angular-js modules=&quot;mymodule&quot;&gt;
    &lt;my-component&gt;&lt;/my-component&gt;
  &lt;/crm-angular-js&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-26T19:23:54.387Z
Answers.Text: Fantastic answer - thank you.  I really am looking forward to the afform product, looks like it will make things easier.  I gave up on the angular form and went back to what I've used in the past - the quickforms.  Not ideal but at least these work really well.
Answers.UserDisplayName: Norm Dressler
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-26T20:03:57.620Z
Answers.Text: Well, sort of gave up - I'm looking at the changes you suggest above and will give it a go.  I did try to install/activate the afform extension but it gave me errors and didn't look very nice when it was finished.  I assumed because its alpha/beta it isn't ready.
Answers.UserDisplayName: Norm Dressler
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-27T00:35:49.873Z
Answers.Text: FYI the extension didn't install properly because of a DB error trying to insert into option_group_en_CA with the message no default.  if you install into option_group it fixes the issue (option_group_en_CA is only a view to option_group).
Answers.UserDisplayName: Norm Dressler
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-27T12:18:25.777Z
Answers.Text: Did you get it working?
  FYI - nothing to do with Angular, but you shouldn't do direct db queries in your installer. Use the api and it will take care of the the localized columns/views.
Answers.UserDisplayName: Coleman
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-27T12:26:59.027Z
Answers.Text: I was using the debug output from Civicrm to track the errors.  There were two actually.  Both related to option_group not having a default set for values.  I set default to "" in option_group and option_group_value in order to get the install to work and not constantly throw errors throughout the system.  I can share more details if you like.  It's now installed and looking good and I will spend some time this morning on making my form.
Answers.UserDisplayName: Norm Dressler
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-27T16:15:33.580Z
Answers.Text: Cool. Pls accept this answer if it solved your Angular problem and feel free to post a different question about option groups.
Answers.UserDisplayName: Coleman
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-26T15:59:14.463Z
Answers.LastActivityDate: 2021-05-26T23:58:58.810Z
Answers.LastEditDate: 2021-05-26T23:58:58.810Z
Answers.UserDisplayName: Coleman
Body: <p>Good morning from Canada.  I am trying to create an extension with angularjs forms.  I have followed the development guide and have created the angularjs page but I cannot get it to display in CiviCRM.  I have a Tabset function used with Events, it calls the php page, which in turn I have the AngularLoader configuration.  When it gets to the useApp() command I get an Unknown Path error.  The examples in the doc don't go as far as to show how to do this within an extension or as a new tab under event.  Even if you can point me to an example extension, I can analyse it to try and figure it out.  The default_route value in the useApp() command I'm assuming is the ang entry in angular?  When I do a cv ang:html:list the page I want is listed (as well as ang:module:list has the module).  Thanks for any advance or help you can give.
  I ran all of the suggested civix commands from the documentation.
  From the php called from the extension:
  ...</p>
  <pre><code>$loader = new \Civi\Angular\AngularLoader();
  $loader-&gt;setModules(array('trialadmin'));
  $loader-&gt;setPageName('TrialDetails');
  //$loader-&gt;useApp(['defaultRoute' =&gt; '/trialadmin']);
  $loader-&gt;load();
  parent::run();
  </code></pre>
  <p>And in my module I have</p>
  <pre><code>if ($eventID) {
  $url = CRM_Utils_System::url( 'civicrm/event/manage/TrialAdmin', &quot;reset=1&amp;force=1&amp;eventid=$eventID&amp;snippet=5&amp;angularDebug=1&quot; );
  error_log($url);
  $tab['Administration'] = array(
    'title' =&gt; &quot;Administration&quot;,
    'link' =&gt; $url,
    'valid' =&gt; 1,
    'active' =&gt; 1,
    'current' =&gt; false,
  );
  </code></pre>
  <p>output from cv ang:module:list
  trialadmin        | civicrm/a                   | crmUi, crmUtil, ngRoute</p>
  <p>output from cv ang:html:list
  trialadmin/TrialDetails.html</p>
  <p>I've tried different arrangements of the defaultroute but I'm not clear on why I'm getting the unknown path error.  If I comment out the useApp line it continues on to use the *.tpl that I originally had in place.  I wanted to do this with the newer forms format rather than the quickforms as suggested in the docs.</p>
  
Tags: <civievent><extension><angular>
Title: Angularjs called from an extension?
ThreadText: # Angularjs called from an extension?
  
  (Asked by: username_0 on 2021-05-24)
  
  Good morning from Canada.  I am trying to create an extension with angularjs forms.  I have followed the development guide and have created the angularjs page but I cannot get it to display in CiviCRM.  I have a Tabset function used with Events, it calls the php page, which in turn I have the AngularLoader configuration.  When it gets to the useApp() command I get an Unknown Path error.  The examples in the doc don't go as far as to show how to do this within an extension or as a new tab under event.  Even if you can point me to an example extension, I can analyse it to try and figure it out.  The default_route value in the useApp() command I'm assuming is the ang entry in angular?  When I do a cv ang:html:list the page I want is listed (as well as ang:module:list has the module).  Thanks for any advance or help you can give.
  I ran all of the suggested civix commands from the documentation.
  From the php called from the extension:
  ...
  $loader = new \Civi\Angular\AngularLoader();
  $loader->setModules(array('trialadmin'));
  $loader->setPageName('TrialDetails');
  //$loader->useApp(['defaultRoute' => '/trialadmin']);
  $loader->load();
  parent::run();
  
  And in my module I have
  if ($eventID) {
  $url = CRM_Utils_System::url( 'civicrm/event/manage/TrialAdmin', "reset=1&force=1&eventid=$eventID&snippet=5&angularDebug=1" );
  error_log($url);
  $tab['Administration'] = array(
    'title' => "Administration",
    'link' => $url,
    'valid' => 1,
    'active' => 1,
    'current' => false,
  );
  
  output from cv ang:module:list
  trialadmin        | civicrm/a                   | crmUi, crmUtil, ngRoute
  output from cv ang:html:list
  trialadmin/TrialDetails.html
  I've tried different arrangements of the defaultroute but I'm not clear on why I'm getting the unknown path error.  If I comment out the useApp line it continues on to use the *.tpl that I originally had in place.  I wanted to do this with the newer forms format rather than the quickforms as suggested in the docs.
  
  **Tags:** civievent, extension, angular
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_0 on 2021-05-25. Score: 2 | Accepted answer
  
  Ok, sorted it out with some suggestions and examples.
  
  > $loader = new \Civi\Angular\AngularLoader();
  > $loader->setModules(array('trialadmin'));
  > $loader->setPageName('Administration');
  > $loader->useApp(['activeRoute' => '/trialadmin/trialdetails']);
  > $loader->load();
  
  Worked with this, but I also used the trace and debug in the browser to determine there likely was another issue with the form actually loading. Regardless, I've been able to sort it out.
  
  
  ---
  
  ### Answer by username_1 on 2021-05-26. Score: 1
  
  You are trying to inject an angular snippet into an otherwise non-angular page, and you're wanting to place it into a new tab in the Manage Events page. This is doable but there are a few things to understand:
  
  Yours might not be the only Angular snippet on the page. Other extensions may want to add them in the future.
  Angular routing requires control of the URL, which your snippet shouldn't assume it has, so I don't recommend using crmApp or ng-route.
  Tab content loads via ajax by default, but it's also possible to pre-load it by supplying a "template" property. This makes Angular stuff simpler.
  
  I recently faced these same challenges while adding this feature to the new Form Builder (Afform) extension, and ended up improving the way AngularJS loads in Civi. It's available in version 5.37+ and I highly recommend you start using this new service:
  In your hook you'd do this:
  function my_hook_civicrm_tabset($tabsetName, &$tabs, $context) {
    //check if the tab set is Event manage
    if ($tabsetName == 'civicrm/event/manage') {
      if (!empty($context['event_id'])) {
        // Add our Angular module to the page
        Civi::service('angularjs.loader')->addModules(['trialadmin']);
        // Add the tab
        $tab['Administration'] = [
          'title' => "Administration",
          'template' => 'path/to/your/template.tpl',
          'valid' => 1,
          'active' => 1,
          'current' => false,
        ];
      }
    }
  }
  
  Note that I didn't supply a URL but instead gave a 'template' which will cause the tab content to load immediately. So now you've got your module loaded and don't have to worry about ajax for the tab content.
  In your tpl file you need to initialize your Angular module. This will look a little different than the docs which use crmApp and ng-route. It's actually going to be a lot simpler. All you do is add a tag which tells Civi to boostrap Angular and load your module, then just have your module do it's thing.
  So skip all the stuff about routes and controllers. Best practice is to just define a module and a component.
  E.g.
  (function(angular, $, _) {
    angular.module('mymodule', CRM.angRequires('mymodule'));
  
    angular.module('mymodule').component('myComponent' {
      // do your thing
    });
  })(angular, CRM.$, CRM._);
  
  Then your .tpl file would look like this:
  
  > **Comments:**
  > **username_0**: Fantastic answer - thank you.  I really am looking forward to the afform product, looks like it will make things easier.  I gave up on the angular form and went back to what I've used in the past - the quickforms.  Not ideal but at least these work really well.  
  > **username_0**: Well, sort of gave up - I'm looking at the changes you suggest above and will give it a go.  I did try to install/activate the afform extension but it gave me errors and didn't look very nice when it was finished.  I assumed because its alpha/beta it isn't ready.  
  > **username_0**: FYI the extension didn't install properly because of a DB error trying to insert into option_group_en_CA with the message no default.  if you install into option_group it fixes the issue (option_group_en_CA is only a view to option_group).  
  > **username_1**: Did you get it working? FYI - nothing to do with Angular, but you shouldn't do direct db queries in your installer. Use the api and it will take care of the the localized columns/views.  
  > **username_0**: I was using the debug output from Civicrm to track the errors.  There were two actually.  Both related to option_group not having a default set for values.  I set default to "" in option_group and option_group_value in order to get the install to work and not constantly throw errors throughout the system.  I can share more details if you like.  It's now installed and looking good and I will spend some time this morning on making my form.  
  > **username_1**: Cool. Pls accept this answer if it solved your Angular problem and feel free to post a different question about option groups.  
  
  ---
  
  