Note: I have seen several questions like my title, but they don't solve my problem. Like:
- Angular2 Parent Component with multiple instances of child component (just code error)
- Instance Angular 2 Component Two times (this is about bootstrapping, not just components)
Situation
I have several template driven forms inside my angular application, with multiple date fields. I have made a special component (DatePickerComponent) that I insert as a child component in al these forms.
Problem
The variables inside the components are shared. Angular probably instantiates the same object, but I want different instances! I am note sure how to do this.
What I think is the solution
It probably has something to do with where you declare the DatepickerComponent. I declared it in the app.module.ts, but this creates one instance for the whole application. I don't know how to make sure that my parent component is forced to use two different child components.
Reasoning
I am doing this in a seperate component, because I don't have a date picker yet. Right now its a textbox with a pattern form validation. Later on I will make something better (a real date picker), and I don't want to copy paste code everywhere and make mistakes. With using 1 component, this is easily done.
Concrete code
import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {ControlContainer, NgForm} from "@angular/forms";
@Component({
selector: 'app-datepicker-component',
templateUrl: './datepicker.component.html',
// Add viewProviders, so the input will be treated part of the form in the parent.
// https://stackoverflow.com/questions/39242219/angular2-nested-template-driven-form
viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
export class DatepickerComponent implements OnInit { // stuff }
HTML file:
<div class="form-group">
<label for="date" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<input type="text" name="date" id="date" class="form-control" [ngModel]="date" (ngModelChange)="dateChange.emit($event)"
#inputdate="ngModel" [required]="required" pattern="^(?:(?:31(\/|-|\.)(?:0[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)02\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)\d{2})$"/>
<span class="help-block" *ngIf="required && inputdate.invalid && inputdate.errors.required && (inputdate.dirty || inputdate.touched || triedSubmit)">Datum is verplicht.</span>
<span class="help-block" *ngIf="inputdate.invalid && inputdate.errors.pattern && (inputdate.dirty || inputdate.touched || triedSubmit)" >Datum moet formaat dd-MM-yyyy hebben.</span>
</div>
</div>
In some other page I use:
<form>
<app-datepicker-component label="Actief vanaf" [(date)]="date1" [required]="true" [triedSubmit]="triedSubmit"></app-datepicker-component>
<app-datepicker-component label="Actief tot" [(date)]="date2" [required]="false" [triedSubmit]="triedSubmit"></app-datepicker-component>
</form>
The AppModule:
@NgModule({
declarations: [
AppComponent,
// stuff
DatepickerComponent
],
imports: [
// stuff
],
providers: [
// stuff],
bootstrap: [AppComponent]
})
export class AppModule { }
Things that go wrong
The date variable is shared because the same instance is used, which I don't want. Also if the validation triggers for one of the components, it will think the other components are invalid (which they aren't).