Search code examples
javascripthtmlangularjstemplatesangular-template

Reuse html template in Angular project


I have this html template file, range-details-dialog.tpl.html

<div class="modal-header clearfix text-left">
    <h5>Update Range</h5>
</div>
<div class="modal-body">
    <form name="form" role="form" class="ng-pristine ng-valid" novalidate ng-submit="updateRange()">
        <div class="form-group-attached">
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group form-group-default input-group p-l-10 p-r-10" ng-class="{ 'has-error' : form.$invalid }">
                        <p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>
                    </div>
                </div>
            </div>
        </div>
    </form>
    <div class="row">
        <div class="col-sm-8"></div>
        <div class="col-sm-4 m-t-10 sm-m-t-10">
            <button type="button" class="btn btn-primary btn-block m-t-5" 
             ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>
        </div>
    </div>
</div>

Then I want to have another file forced-range-details-dialog.tpl.html These two files could be one file instead with dynamically populated placeholders. These are the places were substitution would be needed:

  1. <h5>Update Range</h5> would become <h5>Update Forced Range</h5>

  2. <p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>

    would become:

    <p ng-show="form.forcedRangeDaily.$error.min" class="help-block">Forced Daily range more than £5</p>

  3. ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>

    , ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateForcedRange()">Update</button>

Is there a way to avoid having two separate template files for the above? Could you please provide some examples, links, or pointers as to how that can be achieved?

Also, I see in the answers that a solution would be to add a boolean parameter inside the component and then call it twice. I am not sure how to call the component though. I have pasted my component below:

 angular.module('app.investment.rangeDetails')
  .component('pxForcedLimitAmount', {
      templateUrl: '/assets/js/apps/range/range-details-dialog.tpl.html',
      bindings: {
          amount: '<',
          isRequest: '<?',
          requestedAt: '<?',
          @Input() isForced: boolean  //<<----I added this based on answers below
      },
      controller: [function () {
          var ctrl = this;

          ctrl.$onInit = function () {
              ctrl.isRequest = ctrl.isRequest === true || false;
          };
      }],
  });

Solution

  • Seems like only the placeholders need to change, so you can use a variable to decide what placeholder to display on the template. For example:

    isForced: boolean;
    
    ngOnInit() {
       this.isForced = true; // decide how you want to toggle this
    }
    

    on the template:

    <h5 *ngIf="!isForced">Update Range</h5>
    <h5 *ngIf="isForced">Update Forced Range</h5>
    

    and

    <p *ngIf="!isForced" ng-show="form.rangeDaily.$error.min" class="help-block">
         Daily range more than £5</p>
    
    
    <p *ngIf="isForced" ng-show="form.forcedRangeDaily.$error.min" class="help-block">
         Forced Daily range more than £5</p>
    

    you can do the same for other tags as well.


    From the comments, one way to "determine" the value for isForced is to introduce an input property to the component i.e.

    @Input() isForced: boolean;
    

    and invoke the component from elsewhere like:

    <app-user [isForced]="true"></app-user>