Answers.Body: <p>If you're ok with it not being tightly integrated (i.e. automatically available in the xml or to the api), then you can do something like below, which adds a field labelled "Boo" to the case type edit screen.</p>
  
  <p>Thanks for asking this question. It's probably helped me more than you, since it's helped clarify for me how this all works. And it occurs to me that customizing an existing form is probably a much more likely task for developers than writing your own angular form from scratch, which is what all the tutorials show.</p>
  
  <pre><code>function myextension_civicrm_alterAngular(\Civi\Angular\Manager $angular) {
    $changeSet = \Civi\Angular\ChangeSet::create('add_casetype_custom_field')
      -&gt;alterHtml('~/crmCaseType/caseTypeDetails.html',
        function (phpQueryObject $doc) {
          $doc-&gt;find('div.crm-group')-&gt;append('
            &lt;fieldset class="crm-collapsible"&gt;
              &lt;legend class="collapsible-title"&gt;{{ ts(\'My Custom Fields\') }}&lt;/legend&gt;
              &lt;div ng-controller="CustomFieldCtrl"&gt;
                &lt;div crm-ui-field="{name: \'mycustomfield\', title: ts(\'Boo\')}"&gt;
                  &lt;input crm-ui-id="mycustomfield" class="crm-form-text" name="mycustomfield" ng-model="mymodel.cusfield"&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/fieldset&gt;
          ');
        });
    $angular-&gt;add($changeSet);
  
    CRM_Core_Resources::singleton()-&gt;addScriptFile('my.extension.name', 'js/angCustomField.js');
  }
  </code></pre>
  
  <p>Reference: <a href="https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/" rel="nofollow noreferrer">https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/</a></p>
  
  <p>And here is the contents of js/angCustomField.js:</p>
  
  <pre><code>(function(angular, $) {
    var crmCaseType = angular.module('crmCaseType');
    crmCaseType.controller('CustomFieldCtrl', function($scope) {
      // Need to replace this with an ajax call right here to look up the value from the db.
      $scope.mymodel = { cusfield: 'value looked up from db' };
  
      // just show that this is executing and we have the right id
      console.log($scope.caseType.id);
  
      // alias the real save() function so that we can do our stuff too
      var proxiedSave = $scope.$parent.$parent.save;
      $scope.$parent.$parent.save = function() {
        console.log($scope.caseType.id);
        console.log($scope.mymodel.cusfield);
  
        //
        // Do ajax api or whatever here to save the value to db
        //
        // IMPORTANT: Always validate the input server-side before using it even if you have javascript validation client-side since that can be easily bypassed. This isn't specific to angular it just seems to be ignored in all the angular tutorials. Even a plain html form with e.g. a select list can still submit values not in the select list - always need to validate server-side.
  
        // Now call the original save
        return proxiedSave.apply(this);
      }
    });
  })(angular, CRM.$);
  </code></pre>
  
  <p>Some notes:</p>
  
  <ul>
  <li>Note we're adding our own nested child controller in the line that has <code>ng-controller="CustomFieldCtrl"</code>. This matches up to the controller in our js file.</li>
  <li>The <code>ng-model="mymodel.cusfield"</code> value HAS TO HAVE A DOT IN IT. It just doesn't work if it doesn't. This matches up to the <code>$scope.mymodel = ...</code> line in our js file.</li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-11T11:51:09.570Z
Answers.Text: I think the hook sits behind a cache so you can't count on it being fired every time the angular page loads. So using CRM_Core_Resources directly probably won't work.
Answers.UserDisplayName: Coleman
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-30T23:36:23.867Z
Answers.LastActivityDate: 2019-07-05T19:25:04.377Z
Answers.LastEditDate: 2019-07-05T19:25:04.377Z
Answers.UserDisplayName: Demerit
Body: <p>I want to add a field on Case type setting (civicrm/a/#/caseType/1 which is build in angular js) either just below the description field or as a tab besides case role tab. What is the easiest way to do this?</p>
  
  <p>Civi version - 5.14.0</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-06-29T13:28:57.283Z
Comments.Text: Do you also need it to be stored in the xml definition and/or available from api CaseType.get? I've looked into that part before and I didn't see a way to do it without hacking core.
Comments.UserDisplayName: Demerit
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-06-29T13:29:55.100Z
Comments.Text: Yes i need to save that into different table probably as a custom field for case type.
Comments.UserDisplayName: Pradeep Nayak
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-06-29T13:32:07.903Z
Comments.Text: As part of this https://lab.civicrm.org/dev/core/issues/1046 I was thinking about proposing a hook that could be a first step towards custom fields for case types, but I'm still in planning stages.
Comments.UserDisplayName: Demerit
Tags: <civicase><angular>
Title: Add field on Case type form
ThreadText: # Add field on Case type form
  
  (Asked by: username_0 on 2019-06-29)
  
  I want to add a field on Case type setting (civicrm/a/#/caseType/1 which is build in angular js) either just below the description field or as a tab besides case role tab. What is the easiest way to do this?
  
  Civi version - 5.14.0
  
  **Tags:** civicase, angular
  
  > **Comments:**
  > **username_1**: Do you also need it to be stored in the xml definition and/or available from api CaseType.get? I've looked into that part before and I didn't see a way to do it without hacking core.  
  > **username_0**: Yes i need to save that into different table probably as a custom field for case type.  
  > **username_1**: As part of this https://lab.civicrm.org/dev/core/issues/1046 I was thinking about proposing a hook that could be a first step towards custom fields for case types, but I'm still in planning stages.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-06-30. Score: 4 | Accepted answer
  
  If you're ok with it not being tightly integrated (i.e. automatically available in the xml or to the api), then you can do something like below, which adds a field labelled "Boo" to the case type edit screen.
  
  Thanks for asking this question. It's probably helped me more than you, since it's helped clarify for me how this all works. And it occurs to me that customizing an existing form is probably a much more likely task for developers than writing your own angular form from scratch, which is what all the tutorials show.
  
  ```
  function myextension_civicrm_alterAngular(\Civi\Angular\Manager $angular) {
    $changeSet = \Civi\Angular\ChangeSet::create('add_casetype_custom_field')
      ->alterHtml('~/crmCaseType/caseTypeDetails.html',
        function (phpQueryObject $doc) {
          $doc->find('div.crm-group')->append('
            <fieldset class="crm-collapsible">
              <legend class="collapsible-title">{{ ts(\'My Custom Fields\') }}</legend>
              <div ng-controller="CustomFieldCtrl">
                <div crm-ui-field="{name: \'mycustomfield\', title: ts(\'Boo\')}">
                  <input crm-ui-id="mycustomfield" class="crm-form-text" name="mycustomfield" ng-model="mymodel.cusfield">
                </div>
              </div>
            </fieldset>
          ');
        });
    $angular->add($changeSet);
  
    CRM_Core_Resources::singleton()->addScriptFile('my.extension.name', 'js/angCustomField.js');
  }
  
  ```
  
  Reference: <https://docs.civicrm.org/dev/en/latest/framework/angular/changeset/>
  
  And here is the contents of js/angCustomField.js:
  
  ```
  (function(angular, $) {
    var crmCaseType = angular.module('crmCaseType');
    crmCaseType.controller('CustomFieldCtrl', function($scope) {
      // Need to replace this with an ajax call right here to look up the value from the db.
      $scope.mymodel = { cusfield: 'value looked up from db' };
  
      // just show that this is executing and we have the right id
      console.log($scope.caseType.id);
  
      // alias the real save() function so that we can do our stuff too
      var proxiedSave = $scope.$parent.$parent.save;
      $scope.$parent.$parent.save = function() {
        console.log($scope.caseType.id);
        console.log($scope.mymodel.cusfield);
  
        //
        // Do ajax api or whatever here to save the value to db
        //
        // IMPORTANT: Always validate the input server-side before using it even if you have javascript validation client-side since that can be easily bypassed. This isn't specific to angular it just seems to be ignored in all the angular tutorials. Even a plain html form with e.g. a select list can still submit values not in the select list - always need to validate server-side.
  
        // Now call the original save
        return proxiedSave.apply(this);
      }
    });
  })(angular, CRM.$);
  
  ```
  
  Some notes:
  
  * Note we're adding our own nested child controller in the line that has `ng-controller="CustomFieldCtrl"`. This matches up to the controller in our js file.
  * The `ng-model="mymodel.cusfield"` value HAS TO HAVE A DOT IN IT. It just doesn't work if it doesn't. This matches up to the `$scope.mymodel = ...` line in our js file.
  
  > **Comments:**
  > **username_2**: I think the hook sits behind a cache so you can't count on it being fired every time the angular page loads. So using CRM_Core_Resources directly probably won't work.  
  
  ---
  
  