Cannot read variable data of child view - javascript

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.

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 - Pass input to ng-content component

I have a modal component with ng-content. In this ng-content I can pass other components with injector. I need to pass anyway an object inside it for editing data. But I need some help. This is the modal component html:
<div class="modal">
<div class="modal-body">
this is my Object: {{model | json}}
<ng-content></ng-content>
</div>
<div class="modal-footer">
<button (click)="sendMessage()">success</button>
<button>abort</button>
</div>
</div>
The components inside ng-content may vary. In my example I have an input. I need to pass a model inside that components.
I use a service with injector to pass the content into my modalComponent, and in the function "open" I defined a parameter obj that's the object that I need to see into ng-content component. (The parameter is stored inside "model" input on my Modal component).
#Injectable()
export class ModalService {
dialogComponentRef: ComponentRef<ModalComponent>;
private subject = new Subject<any>();
open(content: any, obj: any) {
const contentComponentFactory = this.cfResolver.resolveComponentFactory(content);
const modalComponentFactory = this.cfResolver.resolveComponentFactory(ModalComponent);
const contentComponent = contentComponentFactory.create(this.injector);
const modalComponent = modalComponentFactory.create(this.injector, [[contentComponent.location.nativeElement]]);
modalComponent.instance.model = obj;
this.dialogComponentRef = modalComponent;
document.body.appendChild(modalComponent.location.nativeElement);
this.appRef.attachView(contentComponent.hostView);
this.appRef.attachView(modalComponent.hostView);
}
}
This is my modalComponent Class:
export class ModalComponent {
#Input() model: any;
sendMessage() {
this.modalService.sendMessage();
}
constructor(private modalService: ModalService) {}
}
Therefore I defined a component with this html:
<input type="text" value="name" placeholder="name">
Inside this input I desire to see the object for editing this value.
I can't find a solution for having the object inside the content-component....I need it because I would have a form where I must edit some values.
This is my stackblitz example: Example
What you can do is assign the formData to a property of a service and then read that property in the content component's ngOnInit(), I tried below code and its working for me.
#Injectable()
export class ModalService {
dialogComponentRef: ComponentRef<ModalComponent>;
formData:any;
private subject = new Subject<any>();
open(content: any, obj: any) {
this.formData = obj;
const contentComponentFactory = this.cfResolver.resolveComponentFactory(content);
const modalComponentFactory = this.cfResolver.resolveComponentFactory(ModalComponent);
const contentComponent = contentComponentFactory.create(this.injector);
const modalComponent = modalComponentFactory.create(this.injector, [[contentComponent.location.nativeElement]]);
modalComponent.instance.model = obj;
this.dialogComponentRef = modalComponent;
document.body.appendChild(modalComponent.location.nativeElement);
this.appRef.attachView(contentComponent.hostView);
this.appRef.attachView(modalComponent.hostView);
}
}
and in ngOnInit() of content-component,
ngOnInit() {
this.name = this.modalService.formData.name;
}
However you can try to wrap this property in some function inside service, rather than accessing the property directly(getFormData() or something)

How to pass data when changing views using ng-template

I have a component that has a dynamic view, which I am implementing using an ng-template.
The following is that component, lets say parent.component.ts.
#Component({
...
template: '<div><ng-template child-area></ng-template></div>',
...
})
export class ParentComponent implements OnInit {
#ViewChild(ChildAreaDirective) childArea: ChildAreaDirective;
loadComponent (details) {
let _vcf = this.childArea.viewContainerRef;
let _cf= resolveComponentFactory(childrenList[details.name]);
// How do I pass the options object from here into the child component??
this.childOptions = details.options;
let componentRef = _vcf.createComponent(_cf);
}
}
The child.component.ts is written like this:
#Component ({
template: '<div>{{ title }}</div>'
})
I want to call the loadComponent method like this:
parent.loadComponent({ name: 'choose-doc', options: {title: "Main File"} });
How can I pass the options object into the child component, so that the title gets the value 'Main File'?
componentRef has the attribute instance which is the actual instance of the created component. From this instance, you can access to all public attributes and functions of the component.
You can map your options inside a function on the component or just set them from loadComponent.
Check the class doc: https://angular.io/api/core/ComponentRef#instance

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.

How can I pass values into component?

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>

Categories

Resources