Reputation: 424
We are using AngularJS 1.6 and bootstrap 4.3.1 in our project to build the UI. Now I want to build a simple component which basically makes using bootstrap's form-group elements easier.
I tried writing the component like that:
Template:
<div class="form-group">
<label
for="input-{{::$ctrl.name}}"
class="input-label mb-1"
ng-class="{'disabled': $ctrl.isDisabled, 'required': $ctrl.isRequired}"
ng-bind="::$ctrl.label">
</label>
<input
tabindex="{{$ctrl.tabindex}}"
ng-readonly="$ctrl.isReadonly"
ng-model="$ctrl.model"
type="{{::$ctrl.type}}"
id="input-{{::$ctrl.name}}"
class="form-control"
ng-class="{'negative': $ctrl.hasNegativeStyle}"
ng-required="$ctrl.isRequired">
JavaScript:
(function () {
'use strict';
var component = {
templateUrl: 'app/components/bootstrap/form-group-input/form-group-input.component.html',
bindings: {
name: '@',
label: '@',
model: '<',
isReadonly: '<',
isRequired: '<',
isDisabled: '<',
hasNegativeStyle: '<',
type: '@',
tabindex: '@'
}
};
angular
.module('collphir.common')
.component('cwpFormGroupInput', component);
})();
Problem now is the model-binding. Changing the input in the component won't affect the parent's model, because it's one-way-binding. But how can I achieve that without gong back to the old two-way-binding (which we don't want cause we want to mgirate to Angular anytime soon)?
Upvotes: 0
Views: 66
Reputation: 424
I found a way to achieve what I want:
JavaScript:
(function () {
'use strict';
var component = {
templateUrl: 'app/components/bootstrap/form-group-input/form-group-input.component.html',
bindings: {
name: '@',
label: '@',
model: '<',
isReadonly: '<',
isRequired: '<',
isDisabled: '<',
hasNegativeStyle: '<',
type: '@',
tabindex: '@',
modelChange: '&'
}
};
angular
.module('collphir.common')
.component('cwpFormGroupInput', component);
})();
HTML-Template:
<div class="form-group">
<label
for="input-{{::$ctrl.name}}"
class="input-label mb-1"
ng-class="{'disabled': $ctrl.isDisabled, 'required': $ctrl.isRequired}"
ng-bind="::$ctrl.label">
</label>
<input
tabindex="{{$ctrl.tabindex}}"
ng-readonly="$ctrl.isReadonly"
ng-model="$ctrl.model"
type="{{::$ctrl.type}}"
id="input-{{::$ctrl.name}}"
class="form-control"
ng-class="{'negative': $ctrl.hasNegativeStyle}"
ng-change="$ctrl.modelChange({$event: $ctrl.model})"
ng-required="$ctrl.isRequired">
</div>
Example use of this component:
<cwp-form-group-input
class="mb-2"
name="brutto"
label="{{$ctrl.text.labelBrutto}}"
model="$ctrl.sVEinkommen"
is-readonly="$ctrl.isReadonly"
type="number"
model-change="$ctrl.sVEinkommen=$event"
tabindex="1">
</cwp-form-group-input>
Upvotes: 0
Reputation: 2696
If you want a model change in a child component to also be reflected in its parent component, you have to use two-way binding. So in your component, you can set your binding like this:
bindings: {
// ...
model: '=',
// ...
}
The =
denotes two-way binding, while the <
denotes one-way binding. See this quote directly from the AngularJS documentation:
If you pass an object to a component like this -
bindings: {item: '='}
, and modify one of its properties, the change will be reflected in the parent component.
Upvotes: 0