How to pass multiple parameter to @Directives (@Components) in Angular with TypeScript?
JavascriptAngularTypescriptAngular6Javascript Problem Overview
Since I've created @Directive
as SelectableDirective
, I'm little bit confused, about how to pass more than one value to the custom directive. I have searched a lot but didn't get proper solution in Angular with Typescript.
Here is what my sample code is:
Parent Component as MCQComponent
:
import { Component, OnInit } from '@angular/core';
import { Question } from '../question/question';
import { AppService } from '../app.service/app.service';
import { SelectableDirective } from '../selectable.directive/selectable.directive';
import { ResultComponent } from '../result-component/result.component';
@Component({
selector: 'mcq-component',
template: "
.....
<div *ngIf = 'isQuestionView'>
<ul>
<li *ngFor = 'let opt of currentQuestion.options'
[selectable] = 'opt'
(selectedOption) = 'onOptionSelection($event)'>
{{opt.option}}
</li>
</ul>
.....
</div>
"
providers: [AppService],
directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
private currentIndex:any = 0;
private currentQuestion:Question = new Question();
private questionList:Array<Question> = [];
....
constructor(private appService: AppService){}
....
}
This is a parent component having custom directive [selectable] which takes one param called opt.
Here is the code for this directive:
import { Directive, HostListener, ElementRef, Input, Output, EventEmitter } from '@angular/core'
import { Question } from '../question/question';
@Directive({
selector: '[selectable]'
})
export class SelectableDirective{
private el: HTMLElement;
@Input('selectable') option:any;
...
}
So here I want to pass more parameters from parent component, how do I achieve this?
Javascript Solutions
Solution 1 - Javascript
From the Documentation
> As with components, you can add as many directive property bindings as
> you need by stringing them along in the template.
>
> Add an input property to HighlightDirective
called defaultColor
:
>
> @Input() defaultColor: string;
Markup
>
> Highlight me too! >
> > Angular knows that thedefaultColor
binding belongs to the HighlightDirective
because you made it public with the @Input
> decorator.
>
> Either way, the @Input
decorator tells Angular that this property is
> public and available for binding by a parent component. Without
> @Input
, Angular refuses to bind to the property.
For your example
With many parameters
Add properties into the Directive
class with @Input()
decorator
@Directive({
selector: '[selectable]'
})
export class SelectableDirective{
private el: HTMLElement;
@Input('selectable') option:any;
@Input('first') f;
@Input('second') s;
...
}
And in the template pass bound properties to your li
element
<li *ngFor = 'let opt of currentQuestion.options'
[selectable] = 'opt'
[first]='YourParameterHere'
[second]='YourParameterHere'
(selectedOption) = 'onOptionSelection($event)'>
{{opt.option}}
</li>
Here on the li
element we have a directive with name selectable
. In the selectable
we have two @Input()
's, f
with name first
and s
with name second
. We have applied these two on the li
properties with name [first]
and [second]
. And our directive will find these properties on that li
element, which are set for him with @Input()
decorator. So selectable
, [first]
and [second]
will be bound to every directive on li
, which has property with these names.
With single parameter
@Directive({
selector: '[selectable]'
})
export class SelectableDirective{
private el: HTMLElement;
@Input('selectable') option:any;
@Input('params') params;
...
}
Markup
<li *ngFor = 'let opt of currentQuestion.options'
[selectable] = 'opt'
[params]='{firstParam: 1, seconParam: 2, thirdParam: 3}'
(selectedOption) = 'onOptionSelection($event)'>
{{opt.option}}
</li>
Solution 2 - Javascript
to pass many options you can pass a object to a @Input decorator with custom data in a single line.
In the template
<li *ngFor = 'let opt of currentQuestion.options'
[selectable] = 'opt'
[myOptions] ="{first: opt.val1, second: opt.val2}" // these are your multiple parameters
(selectedOption) = 'onOptionSelection($event)' >
{{opt.option}}
</li>
so in Directive class
@Directive({
selector: '[selectable]'
})
export class SelectableDirective{
private el: HTMLElement;
@Input('selectable') option:any;
@Input('myOptions') data;
//do something with data.first
...
// do something with data.second
}
Solution 3 - Javascript
Another neat option is to use the Directive
as an element and not as an attribute.
@Directive({
selector: 'app-directive'
})
export class InformativeDirective implements AfterViewInit {
@Input()
public first: string;
@Input()
public second: string;
ngAfterViewInit(): void {
console.log(`Values: ${this.first}, ${this.second}`);
}
}
And this directive can be used like that:
<app-someKindOfComponent>
<app-directive [first]="'first 1'" [second]="'second 1'">A</app-directive>
<app-directive [first]="'First 2'" [second]="'second 2'">B</app-directive>
<app-directive [first]="'First 3'" [second]="'second 3'">C</app-directive>
</app-someKindOfComponent>`
Simple, neat and powerful.
Solution 4 - Javascript
Similar to the above solutions I used @Input()
in a directive and able to pass multiple arrays of values in the directive.
selector: '[selectorHere]',
@Input() options: any = {};
Input.html
<input selectorHere [options]="selectorArray" />
Array from TS file
selectorArray= {
align: 'left',
prefix: '$',
thousands: ',',
decimal: '.',
precision: 2
};