How do I call a function/execute code automatically in Angular? - html

I have code in a function that I need for initialization of other variables. However, this function doesn't get called unless i call it through another tag in html. Is there any way that i can initialize this function or write the code in a way in which the code gets executed automatically as soon as the project starts executing the the website loads?

You should have a look at lifecycle hooks that are used in Angular, here is the link to the documents related.
lifecycle hooks
In here you can read about the OnInit() lifecycle hook which is triggered when a component is loaded ( after constructor ) and is an ideal place to look at initialising variables / calling functions.
public ngOnInit(): void {
this.exampleText = 'Hello Component';
}
just make sure to implement it on your class like so
export class youClassHere implements OnInit {
public exampleText: string;
public ngOnInit(): void {
//executing logic on component load
this.exampleText = 'Hello Component';
}
}

You can implement OnInit event and do it there. Take a look here OnInit. Check here if you want to now more about Lifecycle Hooks. Alternative option is to use constructor. But that's executed on class initialization.
class MyComponent implements OnInit {
ngOnInit() {
// ...
}
}

You can implement OnInit lifecycle in your class and call your function inside OnInit so that it gets called whenever your component gets mounted.

Related

is using array.inclues in templare a performance issue in angular

my component have changeDetection:  ChangeDetectionStrategy.OnPush and component have a array variable
myids:Array<number>;
addId(id:number){
this.myids.push(id)
}
in the template I am using:
<div [class.active]="myids.includes(step.id)"></div>
My question, is it a performance problem to use myids.includes in template ?
Yes it is an performance issue. Everytime the template must be rerendered, this array iteration must be run, also. It's a good choice to run with changeDetectionStragy.OnPush, which minimizes the amount of template rerendering.
Good practice:
You should seperate html templates which are responsible for viewing and the code of your component which are responsible to react of events and bring the model to the view.
The core concept of that is Model-View-Controller. (MVC)
I recommend to calculate your "active" property in the controller or a service.
This property is calculated only one time and can easily bound to your template.
Do it like this:
public class MyComponent {
public isActive: boolean;
private myIds: string[];
constructor() {
this.isActive = false;
this.myIds = [];
}
public ngOnInit(): void {
// load myIds
// this.myIds = this._myIdsService.getIds();
this.isActive = this._myids.includes(step.id);
}
}
And then bind this property to your view...
<div [class.active]="isActive"></div>

Angular: How to call function after the component got the Input data

I have a parent and child component. In the parent I am searching for a user and give the userId via #Input to my child component. This is working.
After my child component is getting the value I want to call a function so that I am getting the card from the user back. How do I do this? I always getting a card is undefined error.
<p (show)="serachForCard()">
User: {{userId}}
Card: {{card.id}}
</p>
My Idea was to call a function but it is still not working.
Function in my ts file:
serachForCard() {
this.cardService.getCardByUserId(this.userId)
.subscribe(
(data: Card) => this.card= data
)
}
Implement OnChanges interface inside your child component and call your function from ngOnChanges method.
#Component({
...
})
export class MyComponent implements OnChanges {
#Input() someInput: string;
ngOnChanges(): void {
// do something with this.someInput
}
}
Documentation: OnChanges
A lifecycle hook that is called when any data-bound property of a directive changes. Define an ngOnChanges() method to handle the changes.

Angular 4 - Custom two way binding

I am trying to implement a custom two way binding between two of my components.
I did read about the naming convention saying that you have to define a #Input() like "test" and then define a #Output() named "testChange".
I couldn't find anything about whether this is still up-to-date or not and I can't get my binding to work.
Some code within parentComponent:
<my-comp [(userGroupIds)]="userGroups"></my-comp>
MyComponent (child):
export class MyComponent implements OnInit, OnDestroy{
#Input() userGroupIds: number[];
#Output() userGroupIdsChange = new EventEmitter<number[]>();
updateValues(){
//here I am iterating through the rows of a table within my component
this.userGroupIds = this.tableRows.map(item => {return item['id']});
this.userGroupdIdsChange.emit(this.userGroupIds);
}
}
parentComponent:
export class parentComponent implements OnInit, OnChanges, OnDestry{
userGroups: number[];
constructor(){
this.userGroups = [];
}
ngOnChanges(changes: SimpleChanges){
if(changes['userGroups']){
// this is never show, ngOnChanges doesn't get fired;
console.log(this.userGroups);
}
}
}
Is there something I am missing? Did the Angular-Team change anything?
Afaik the binding does something like
[userGroupsIds]="userGroups" (userGroupsIdsChange)="userGroupIds=$event"
So I tried setting this myself, but no update either. Only thing that work was passing a function to the eventEmitter.
Your binding works like a charm, it does not trigger the ngOnchanges method, which is the expected behavior.
from the Angular docs :
OnChanges
Lifecycle hook that is called when any data-bound property of a directive changes.
as userGroups is not an #Input() it cannot be a "data-bound property" , its value changing internally will not run the ngOnChanges hook.

Angular 2 functions library

In my application I'll need to create a functions library to be accessed from different components. What is the best way to do this? Do I need to make a service with all the functions or a class or a module or a component?
In this library if I call a function from a component and this function need to access a variable in the caller, will it be possible to do?
If it's just a set of one off helper functions the easiest way is create an #Injectable service with your helper methods then inject that into any component that requires them. You can provide public vars as well so they're accessible in your html.
#Injectable()
export class Helpers {
helper1() { return "hello"; }
helper2(x) { return x + 1 }
}
#Component({
providers: [Helpers],
template: "<div>{{helper1()}}</div>" // will display 'hello'
)}
export class MyComponent {
public helper1: Function = Helpers.helper1;
constructor() {
console.log(Helpers.helper2(5)); // will output '6'
}
}
This works great for a simple set of random utility functions. If you need something more in depth please explain and we can provide alternate solutions.

angular 2 RC4 create component

So here is the problem, I am attempting to create a new component from within a service that is injected within the App Component. I need the new component to be placed within the app component html tag not outside. The thing is I really do not want the app component to have to provide anything to the service I may need to inject the service into other places and hence not have it tightly coupled to the app component. So far I have created a DIV at the end of the app component html and then used #ViewChild to read the ViewContainerRef from this element located within the app component. This is then provided to the service via a function call so that it can make use of createComponent. This allows for the NEW component to be placed within the scope of the app component, not within the body. Unfortunately this is too dependant on the app component providing the ViewContainerRef. Any ideas of how I can create the new component as described.
Code Example
app.component.html
<app-component>
<div #newCompHook></div>
</app-component>
app.component.ts
#ViewChild('newCompHook', {read: ViewContainerRef}) newCompViewRef: ViewContainerRef;
constructor(appService: AppService) {
appService.setViewRef(this.newCompViewRef);
}
app.service.ts
private myViewRef;
constructor(private compiler: ComponentResolver){
this.myViewRef = null;
}
public setViewRef(vr: ViewContainerRef): void {
this.myViewRef = vr; // <-- DO NOT WANT TO DO THIS !!!
}
public createNewComp(childCmp: Type): void {
if (this.myViewRef !== null){
this.compiler.resolveComponent( childCmp ).then((compFactory:ComponentFactory) => this.myViewRef.createComponent(compFactory) )
}
}
createNewComp is called by an external source and may or may not provide the childCmp type to be resolved.
So any ideas of how I can do this without needing to provide anything from the app component ???
If you need to have the viewContainerRef in your service that is the only solution...
But it is not a good practice to generate HCI components in a service. It's the role of other components.
Let's take an exemple : your server send you a list of objects (a list of strings for exemple) and you want to generate a button for each string.
In your service you just manage the string list :
#Injectable()
export class MyService {
private myModel : Array<String> = new Array();
public get MyModel () : Array<String> {
return this.myModel;
}
/// Assume you have method in the service to populate the model...
}
Then it's your component which generate the HCI :
export class AppComponent {
/// Use dependency injection to get service :
constructor (private _myService : MyService){}
public get MyModel () : Array<String> {
return this.myService.MyModel;
}
}
Finally in your component template :
<div>
<ul>
<li *ngFor="let s of MyModel">
<!-- Button with your model text -->
<button>s</button>
</li>
</ul>
</div>
That is a better solution than generate the components in the service because just imagine you don't want buttons list but a togglebuttons list in your HCI, here you just have to change the HTML. The service is still the same, and the components typescipt part is still the same too !