0

In AngularJS >1.5, how can several related components share a common controller with common functionallity while being able to have custom behavior for every distinct component?

For example implementing components for <input> elements of different types (text, number, date ... ), every controller will share the same functionallity (to propagate the component value to parent on value changes for example) so one can write a function for the controller and use it on all of them. But if a custom behavior is needed for some types. How can it be detected which component does the controller belong?

Here is some psudo-code:

var commonController = function() {

    this.$onInit = function() {
        // common code for all types

        // code for a specific type
        // how can I detect here which component is running?
    }
}

angular.module('app')
.component('component01', {
    controller: commonController),
    ...
})
.component('component02', {
    controller: commonController),
    ...
})
.component('component03', {
    controller: commonController),
    ...
})

1 Answer 1

1

I think you can accomplish this by combining all the desired input types into a single common-input component and providing the type as a binding to the component. Then within your CommonController you can display/handle changes based on the set input-type.

I have included a snippet below that should accomplish what something similar to what you are looking for. Notifying the parent component would take adding a callback handler to your bindings that you can pass the updated value and input type to.

angular.module('tester', []);

angular.module('tester').component('commonInput', {
  bindings: {
    inputType: '<'
  },
  controller: CommonController,
  template: `
    <div ng-switch on="$ctrl.inputType">
      <input ng-switch-when="text" type="text" ng-model="$ctrl.text" ng-change="$ctrl.onTextChange()"/>
      <input ng-switch-when="date" type="date" ng-model="$ctrl.date" ng-change="$ctrl.onDateChange()"/>
      <input ng-switch-when="number" type="number" ng-model="$ctrl.number" ng-change="$ctrl.onNumberChange()"/>
    </div>
  `
});

function CommonController() {
  this.$onInit = function() {
    console.log('input type:', this.inputType);
    this.text = '';
    this.date = null;
    this.number = null;
  };
  
  this.onTextChange = function() {
    console.log(this.text);
  };
  
  this.onDateChange = function() {
    console.log(this.date);
  };
  
  this.onNumberChange = function() {
    console.log(this.number);
  };
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>

<div ng-app="tester">
  <common-input input-type="'text'"></common-input>
  <common-input input-type="'date'"></common-input>
  <common-input input-type="'number'"></common-input>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

It's a nice approach. The only con I see is that the bindings will also be common to all input types and it is less clear which ones apply to each one (think of maxlength for text or min, max for number).
Yeah I can see what you mean, could potentially end up exposing a lot of bindings to account for the variety of attributes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.