How can I pass values into component? - javascript

I have this component:
export class MyComponent {
#Input() active:boolean;
constructor() {
console.log(this.active);
}
}
You will notice that I've declared an Input that I pass in like this:
<mycomponent
[active]="1 == 1"></mycomponent>
When this loads, the log statement in the constructor logs undefined. What am I doing wrong?

#Input property bindings are first only available after the ngOnInit,
So you should do :
export class MyComponent {
#Input() active:boolean;
ngOnInit() {
console.log(this.active);
}
}
Also FYI :
From the docs :
ngOnInit
Initializes the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties.
Called once, after the first ngOnChanges.
More on Life Cycle Hooks

Below is an example of how to use this.active in your HTML template:
<div *ngIf='active'>
<span [ngClass]="{'glyphicon-play': active}">
<div>

Related

How to update input value in the same component in angular

Trying to update input value in the same component but not able to update.Getting error like
ERROR
Error: Cannot read properties of undefined (reading 'pop')
So, How to resolve this issue?
table.component.ts:
export class TableComponent implements OnInit {
#Input() names: any;
constructor() {}
ngOnInit() {}
testFn() {
this.names.pop('Test22');
this.names = [...this.names];
console.log(this.names);
}
}
Demo : https://stackblitz.com/edit/angular-pass-table-data-to-input-property-dlsufy?file=src%2Fapp%2Ftable%2Ftable.component.ts
Jay Swaminarayan!
You are doing it slightly wrong while passing the Component Reference.
In ChangeComponent, it is not referencing the table component properly.
In AppComponent HTML the table component must be passed as reference input to the changecomponent.
You may look at this corrected code
https://stackblitz.com/edit/angular-pass-table-data-to-input-property-2ehcxs?file=src%2Fapp%2Ftable%2Ftable.component.html,src%2Fapp%2Ftable%2Ftable.component.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fchange%2Fchange.component.html,src%2Fapp%2Fchange%2Fchange.component.ts,src%2Fapp%2Ftable%2Ftable.component.css

Angular 6 nested ViewChild inside ng-template is null

We are using a modal (ng-bootstrap's one) in our application. That modal looks like:
<ng-template #modal let-modal>
<app-audio #audio></app-audio>
</ng-template>
And it's logic:
#ViewChild('modal')
modal: ElementRef;
#ViewChild('audio')
audio: AudioComponent;
The modal is opened with:
this.modalService.open(this.modal, { size: 'lg' });
Everything fine till here. The modal opens and the audio component is shown. But now, we want to access the logic that is inside the component, and when doing something like:
this.audio.somePublicComponentFunction()
It happens that this.audio is null. I have already tried to get the child with angular's change detector, but cannot find a way to properly link this.audio with the actual component. Any ideas? Thanks a lot.
You can see the issue here: stackblitz.com/edit/angular-ofmpju
You can call the method audio.someFunction() from the template itself.
<ng-template #modal let-modal>
<div style="background-color: red;">
<h1>Modal header</h1>
<app-audio #audio></app-audio>
<!-- on click, call audio comp method someFunction() using its reference -->
<button (click)="audio.someFunction()">Operate with audio from inside modal</button>
</div>
</ng-template>
No need of #ViewChild property here. This should do the trick for you.
Forked demo
You can read the child component without the refrence variable like this
#ViewChild(AudioComponent)
audio: AudioComponent;
This will give you the instance of the child component - where you can access the method
this.audio.someComponentFunction()
Your html
<ng-template #modal let-modal>
<app-audio></app-audio>
</ng-template>
This will solve your issue i think - Happy coding
Update:
Hope i found a workaround for this issue - if in case you want to trigger only one function you can use this method
I have just added a property with getter and setter and triggered the function when we set the value
#Input()
get triggerFunction(): boolean {
return this.runFuntion;
}
set triggerFunction(value: boolean) {
this.runFuntion = value;
this.someFunction();
}
So this causes to trigger the function every time when the model show up - property mentioned above belongs to the child component which is nested inside the <ng-template> so finally the model template will read as mentioned below:
<ng-template #modal let-modal>
<app-audio [triggerFunction]="true"></app-audio>
</ng-template>
Hope this will act a workaround for now - Thanks
For me all this solutions did not work and I still wanted to access my own component inside a third party ng-template. Here is my 'solution'. I don't think this is best practice but a desperate solution to get what I want ;-) It only works for your own components of course.
// mycomponent.ts => component that needs to be accessed
import { Component, Output, EventEmitter, AfterViewInit } from '#angular/core';
#Component({
selector: 'my-component',
templateUrl: './mycomponent.html'
})
export class MyComponent implements AfterViewInit {
#Output() initialized: EventEmitter<MyComponent> = new EventEmitter<MyComponent>();
ngAfterViewInit(): void {
this.initialized.emit(this);
}
reload(): void {
// Do something
}
}
// somecomponent.html => component with <ng-template> holding MyComponent
<ng-template>
<div class="btn-group ml-2">
<my-component (initialized)="onMyComponentInitialized($event)"></my-component>
</div>
</ng-template>
// somecomponent.ts => component with <ng-template> holding MyComponent
import { Component, OnDestroy } from '#angular/core';
import { MyComponent } from '../../my-component';
#Component({
selector: 'some-component',
templateUrl: './some-component.html'
})
export class SomeComponent implements OnDestroy {
private _myComponent: MyComponent = null;
onMyComponentInitialized(component: MyComponent) {
this._myComponent = component;
}
someOtherMethod() {
if (this._myComponent) {
// Call some method on the component
this._myComponent.reload();
}
}
ngOnDestroy() {
this._myComponent = null;
}
}

Angular bind ViewChild to Property in Class

I'm trying to figure out how to bind a view child to a child component of a class inside of my view.
I have a models that emulates binary expression:
export interface IODataExpression{
}
export class ODataExpressionDescriptor implements IODataExpression{
property: ODataProperty;
selectedFunction: ODataFunctionDescriptor;
value: any;
isNegated: boolean = false;
}
export class ODataBinaryExpressionDescriptor implements IODataExpression{
left: IODataExpression;
right: IODataExpression;
operator: ODataBinaryOperators;
}
I have a component class which looks like so:
binaryExpression: ODataBinaryExpressionDescriptor = new ODataBinaryExpressionDescriptor();
binaryOperatorKeys: any;
binaryOperators = ODataBinaryOperators;
#ViewChild('left') leftExpression: OdataSimpleFilterComponent;
the left property points to a component which internally has a property:
odataExpression: ODataExpressionDescriptor = new ODataExpressionDescriptor();
How can I make it so that the binaryExpression.left always equals the view childs leftExpression.odataExpression?
Use an EventEmitter.
In OdataSimpleFilterComponent
#Output() odataExpressionChange = new EventEmitter<ODataExpressionDescriptor>();
Then, whenever tha value changes internally in the component, you do:
this.odataExpressionChange.emit(this.odataExpression);
In the main component, you'll have to do in ngAfterViewInit (or ngAfterViewChecked), to make sure that leftExpression is initialised:
ngAfterViewInit() {
leftExpression.odataExpressionChange.subscribe(data => {
this.binaryExpression.left = data;
}
}
This way, whenever the value changes in the child component, you'll receive a notification (via the subsrcription to the EventEmitter) and can react accordingly.
Of course some details might change, as I can't know all of the details of your implementation.

Javascript Angular 4 Change ngClass from another Component

I currently have this code in my app.component.ts
app.component.html
<div [ngClass]="myclass">
...rest of the content here
</div>
This I have the this:
<button (click)="changeClass('myFavClass')">Change Class to myFavClass</div>
app.component.ts
export class AppComponent {
myclass: string;
changeClass(myclass) {
this.myclass = myclass;
}
}
Now, all this works fine BUT I now want to put the triggering button on another component.
If I put this on another component:
<button (click)="changeClass('myFavClass')">Change Class to myFavClass</div>
How can I get it to change the class?
There are two ways you can do this you can use output with an EventEmit
Or you can set up a service that monitors the changes to a variable and use that as the control point for the change.
Personally, I use services for this instance as its easier to manage the code and its flow.
This answer has all the code in you need to look at.
Changing a value in two different components at the same time Angular 2
Hope that helps
There are at least two options. Subject and Observable or if this another component is a parent you can use #Input.
Subject and Observable method:
angular guide Highly recommended to read whole page.
Some component
export class SomeComponent {
constructor(private ClassService: ClassService) { }
private changeClass(class) {
this.ClassService.changeClass(class);
}
}
Another Component
export class AnotherComponent implements OnInit, OnDestroy {
constructor(private ClassService: ClassService) { }
private class: string = "";
private subscribtion: Subscribtion;
ngOnInit(): void {
this.Subscribtion = this.ClassService.someClass$.subscribe(
(class) => { this.class = class; }
)
}
ngOnDestroy(): void {
this.Subscribtion.unsubscribe();
}
}
Service
#Injectable();
export class ClassService{
constructor() { }
private someClassSource= new Subject<string>();
someClass$= this.someClassSource.asObservable();
changeClass(class) {
this.someClassSource.next(class);
}
}
taken from my answer
#Input method:
angular guide
This is very simple, when you click button changeClass method will change elClass which will be passed to another component by #Input decorator, every change of #Input will cause a detect changes which will detect that value has changed so class will change to myClass.
Parent component
parent.component.html
<another-component [elementClass]="elClass"></another-component>
<button (click)="changeClass('myClass')">change class<button>
parent.component.ts
export class ParentComponnet {
private elClass: string = "";
changeClass(class: string) {
elClass = class;
}
}
Another component (must be child component)
another.component.html
<div [ngClass]="elementClass">
another.component.ts
export class AnotherComponent {
#Input() elementClass: string;
}
There is also Child to Parent interaction via #Output (emitting event) angular guide

Cannot read variable data of child view

I have a component MyComponent and it is declared like this:
export class MyComponent implements IComponent {
...
#Input() Departments: any;
#Input() DropDownOptions: any;
#Input() Data: any[];
...
}
However, there is no property Data, when I try to access from PersonComponent component.
HTML of PersonComponent component:
<fieldset>
<my-comp #myGrid [Options]="ps.Options['myGrid']"></my-comp>
</fieldset>
TypeScript of PersonComponent component:
export class PersonComponent implements OnInit {
#ViewChild('myGrid') myGridComponent: MyComponent;
ngAfterViewInit() {
debugger;
let localData2 = this.myGridComponent.Data; // NO DATA PROPERTY. Undefined
}
ngAfterContentInit() {
debugger;
let localData1 = this.myGridComponent.Data; // NO DATA PROPERTY. Undefined
}
}
Variables that can be seen at debugger of Chrome:
How can I read values of Data property of MyComponent? What am I doing wrong?
#Input Data ... decorator "receives" data from the parent component. You set it via the attribute [Data] inside the parent template. If you don't set it it will be indefined. On the other hand you have [Options] attribute that doesn't have the corresponding #Input in the child.
You can fix it like so:
<fieldset>
<my-comp #myGrid [Data]="person.data"></my-comp>
</fieldset>
where person is an array with data field in parent component.
Please read thoughtfully the documention https://angular.io/guide/template-syntax#inputs-outputs and https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding
And it would be better to not use reserved/too generic name like Data, Options to avoid name collisions and also camel case them.

Categories

Resources