Angular 2 : HTML property binding - html

I'm trying to understand the HTML bindings as I'm new to angular.
Can someone please explain the difference between the following syntax:
<!-- 1 -->
<button name1 = "name2" >test</button>
<!-- 2 -->
<button (name1) = "name2" >test</button>
<!-- 3 -->
<button [name1] = "name2" >test</button>
<!-- 4 -->
<button ([name1]) = "name2" >test</button>
I have seen above in multiple places but could not understand the purpose of each case.
Thank you for the help!

There are two different thinks.. bindings and events:
Here's a live-demo: https://plnkr.co/edit/gfJL9RCyYriqzP9zWFSk?p=preview
Binding
binds just a fixed string
<input value="test" />
one-way binding a fixed string with expression-syntax
<input [value]="'test'" />
one-way binding a variable test with expression-syntax
<input [value]="test" />
one-way binding a variable test
<input value="{{ test }}" />
two-way bindig the variable test to this input
<input [(ngModel)]="test" />
Events
bind click-event to our onClick-function
<button (click)="onClick($event)"></button>
official docs: https://angular.io/docs/ts/latest/guide/template-syntax.html

Here is a practical example of event-binding, string-interpolation, and property binding
import {Component} from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
firstString: string = ' This is using string interpolation coming from a variable in a component ';
secondString: string = 'This is using string interpolation coming from a method in a component ';
thirdString: string = 'This is using property-binding';
forthString: string= 'This is the string before you click';
returnsecondString () {
return this.secondString;
}
onClick(){
this.forthString= 'This is the string after you click'
}
}
<div class="col-lg-1">
<UL class="list-group-item-info">
<!--Format for string interpolation: {{ a string from type script or any string }} -->
<!--Format for property binding: []= "" -->
<!--format for event binding: ()="" -->
<li><p> This is an example of string interpolation : {{firstString}}</p></li>
<li><p> This is an example of string interpolation : {{returnsecondString()}}</p></li>
<li><p [innerHTML]="thirdString"></p></li>
<button class="btn btn-primary" (click)="onClick()"> Click here for Event Binding</button> <hr>
<li><p>{{forthString}}</p></li>
</UL>
</div>

Related

How to pass value from one component to another? (Angular)

I just recently started learning Angular and I have a question. I want to implement a search method to search for a product on my site, I made search.pipe.ts, which works, but the input for input is in the header.component.ts component, and the products array is in the car-list.component.ts component.
car-list.component.html
<div *ngFor="let car of cars | paginate: { itemsPerPage: pageNumber, currentPage: currentPg} | **search:searchStr**" class="col-md-3">
<div class="product box">
<img src="{{'data:image/jpg;base64,' + car.image }}" alt="">
<h3>{{ car.name }}</h3>
<div class="price">{{ car.price | currency:'USD' }}</div>
<button class="btn btn-primary btn-sm">Add to cart</button> <!--(click)="addToCart(tempProduct)"-->
</div>
<br>
</div>
header.component.html
<form class="d-flex me-5">
<input type="text" class="form-control me-2" placeholder="Search cars...">
</form>
header.component.ts
export class HeaderComponent implements OnInit {
searchStr: string = '';
constructor() {
}
ngOnInit(): void {
}
}
search.pipe.ts
#Pipe({
name: 'search'
})
export class SearchPipe implements PipeTransform {
transform(cars: any[], value: any) {
return cars.filter(car => {
return car.name.includes(value);
})
}
}
I want the input values ​​from the header component to be passed to the car-list component so that I can find the product I need.
In this case you can use a shared service where you can pass data from your header component and load that data in your products component.
For further reference - Angular 4 pass data between 2 not related components
use #Input and #Output decorators to communicate between components

Angular NgFor Path Issue

In my Angular Application I have a simple ngFor loop showing logo images like this:
<div *ngFor="let item of list" class="logo-wrapper">
<div class="customer-logo">
<span
class="my-icon"
aria-label="My icon"
[inlineSVG]="'./assets/image/projects/logo/' + item.logo">
</span>
</div>
</div>
This is working fine!
But: If I try to slice the Array to limit the output as follow:
<div *ngFor="let item of list | slice: 0:10; let i = index" class="logo-wrapper">
<div class="customer-logo">
<span
class="my-icon"
aria-label="My icon"
[inlineSVG]="'./assets/image/projects/logo/' + item.logo">
</span>
</div>
</div>
I get this Error : "Object is of type 'unknown'".
Error output:
I really don't know what I'm doing wrong here. I hope someone can point me in the right direction.
Edit: The problem appears as soon as I add a index to the loop.
I tried to add the index to the object like: item.i.logo but its also unknown.
PS: Here is my .ts-file
#Component({
selector: 'app-logo-section',
templateUrl: './logo-section.component.html',
styleUrls: ['./logo-section.component.scss']
})
export class LogoSectionComponent implements OnInit {
list : any
constructor()
{
this.list = getProjects()
console.log(this.list)
}
ngOnInit(): void
{
}
private services = [{
slug : "s-l-u-g",
name : "name",
work : "work",
company : "company",
website : "https://www.google.com",
preview : "text",
logo : "logo.svg"
}]
getProjects()
{
return services
}
}
You would have to change the type of list to any[] instead of any. Update the declaration as follows in your typescript file.
list : any[];
It seems like the SlicePipe deprecates with the ng-inline-svg package because it uses HttpClientModule and works asynchronously.
if you use Array.slice method instead of the SlicePipe in the *ngFor it works fine.
Please find the Stackblitz example.
<div *ngFor="let item of list.slice(0, 10); let i = index" class="logo-wrapper">
<div class="customer-logo">
<span class="my-icon" aria-label="My icon" [inlineSVG]="item.logo"> </span>
</div>
</div>

Angular NgFor loop 2 arrays of objects

I want to loop through two different arrays with ngFor and display them in html.
<div class="form-check ml-5" *ngFor="let item of competencias.competencias; let i = index">
<input class="form-check-input" type="checkbox" [value]="item.id [(ngModel)]="arrayCompetencias[i].checked">
<label class="form-check-label">
<strong> {{ item.id }} </strong> : {{ item.descripcion}}
</label>
</div>
Those 2 arrays has the same length but I want to combine them as to show separate data.
First array has a list of data just to display and is fine.
Second array arrayCompetencias I want just to see if user check the checkbox or not and save it as ngModel.
When trying to get the parameter data in arrayCompetencias[i].checked it through me an error that the field is undefined, but I am initializing them before.
First Array
competencias = [{id: string, descripcion: string}]
Second Array
arrayCompetencias = [{checked: boolean, id: string}]
[(ngModel)]="arrayCompetencias[i].checked">
How can i read only this field into the array and set according User checked or not
I fixed some typos on your code and added some edits.
Try to use this example and it should work perfectly with you.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
competencias = [{id: "1", description: "This is a description"}]
arrayCompetencias = [{checked: true, id: "1"}]
}
<div *ngFor="let item of competencias; let i = index">
<input type="checkbox"
[value]="item.id"
[checked]="arrayCompetencias[i].checked"
(change)="arrayCompetencias[i].checked = !arrayCompetencias[i].checked">
<label>
<strong> {{ item.id }} </strong> : {{ item.description}}
</label>
</div>
Nothing I have changes only a problem in your data.
You can check the code here

Get a value from a HTML form in a Angular 2 ag-grid

I have a form that appears in a modal in my HTML file and i would like to add the values i get form the form in a ag-grid array, and i have no idea how to do this.
This is my file.html
<template #addTrainContent let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title">Ajouter un train</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<input type="radio" name="choiceDirection" /> Gauche
<input type="radio" name="choiceDirection" /> Droite
<input type="number" placeholder="Numéro de matériel" value="nMateriel"/>
<select>
<option>1</option>
<option>52</option>
<option>38</option>
</select>
<input type="checkbox" checked /> Créer dans l'ATS
</div>
<div class="modal-footer">
<button class="btn btn-lg btn-primary" (click)="c(createTrain())">Ajouter le train</button>
<button type="button" class="btn btn-secondary" (click)="c('Close click')">Annuler</button>
</div>
</template>
And i was adding a train with value i chose instead of the ones from the form, like that in my file.ts
createNewTrain() {
var newTrain = {
nMateriel: 97,
nRame: 42,
position: 'TB__BLOC_13',
direction: 'droite',
etat: 'mouvement',
vitesse: '24 km/h'
};
return newTrain;
}
createTrain() {
var newItem = this.createNewTrain();
this.gridOptions.api.addItems( [newItem] );
this.rowCount++;
}
How can i get the value from my form and put it in my ag-grid array?
Thank you for your help
Let's step through this example. Here is the initial setup:
//our root app component
import {Component, Directive, ElementRef} from 'angular2/core'
#Component({
selector: 'my-app',
directives: [],
providers: [],
template: `
<div>
<h2>Hello {{name}}</h2>
<label>Name</label>
<select [(ngModel)]="name" name="Select name" class="ui fluid search selection dropdown">
<option *ngFor="#n of names" [attr.value]="n">{{n}}</option>
</select>
<br>
<button (click)="print()">print</button>
</div>
`,
directives: []
})
export class App {
// name: string = "Jane";
names: string[] = ["John", "Paul", "George", "Ringo"]
print = () => console.log(this.name)
constructor() {
setTimeout(() => {
jQuery('.ui.dropdown').dropdown();
}, 1000);)
}
}
NOTE: MODEL refers to variables in the class App, CONTROLLER refers to functions in the class App, and VIEW refers to the HTML template.
The variable that is of most interest to us is name. Notice that it is currently commented out in the MODEL. However, I have a CONTROLLER that is able to print this.name. What is happening is that Angular notices that it is bound in the VIEW and so it decides to create it for us.
In the <h2> it is a one-way binding, meaning that it takes the value of what is in the MODEL. So if something were to change the value of name in the MODEL, Angular would update the VIEW with the new value.
In the Select there is a two-way binding, meaning that if the value of name in the VIEW gets updated, Angular will notify the MODEL that name is now a new value; Also, if something in the MODEL were to change name then the VIEW would get updated.
For example when you change the select to "Ringo", the MODEL gets updated, then the MODEL updates the VIEW so that the title reads "Hello Ringo"
Now if you uncomment name: string = "Jane", then you are basically setting a default value for name. You might also notice that the title will then read "Hello Jane" but the select remains blank. That is because "Jane" isn't one of the options in the select.
What this means for you:
In your VIEW bind each of your inputs to variables with [(ngModel)] for example:
<input [(ngModel)]="materiel" type="number" placeholder="Numéro de matériel" value="nMateriel"/>
Then in your CONTROLLER for creating a new train you will be able to use that variable as a reference:
createNewTrain() {
var newTrain = {
nMateriel: this.materiel,
nRame: 42,
position: 'TB__BLOC_13',
direction: 'droite',
etat: 'mouvement',
vitesse: '24 km/h'
};
return newTrain;
}
Nothing else is really needed, however I would strongly suggest to add some defaults into your TS file/MODEL for readability's sake and so that each of these variables will have a value:
// somewhere in your TS
materiel: number = 97
I solved my problem by doing this in my file.ts :
(I only changed it for nMateriel for the example)
createNewTrain() {
var newTrain = {
nMateriel: (<HTMLInputElement>document.getElementById("nMateriel")).value,
nRame: 42,
position: 'TB__BLOC_13',
direction: 'droite',
etat: 'mouvement',
vitesse: '24 km/h'
};
return newTrain;
}

How do I get the count of the selected checkboxes and display the count in Angular 2?

I need help displaying the count of a list of checkboxes into the value of a dropdown box. Where do I need to get my count from? The checkboxes are being passed dynamically as an array.
Here is my current code.
DropDownBox Component
<div ngbDropdown class="d-inline-block" [autoClose]="false">
<button class="btn btn-outline-primary" id="dropdownMenu1" ngbDropdownToggle{{title}}`(need to display the count here)`
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu1">
<input type="text" placeholder="{{searchPlaceholder}}" class="searchBox" />
<div *ngFor="let data of datas">
<cst-checkbox [checkBoxValue] = "data" [ngModel]="data.selected"></cst-checkbox>
</div>
</div>
</div>
Checkbox component
<div class="checkbox">
<input type="checkbox" value="{{checkBoxValue}}" />
<label>{{checkBoxValue}}</label>
</div>
The checkbox component is <cst-checkbox> in the dropdown component.
You can create your Custom Pipe to get selected values only, by filtering them up
#Pipe({
name: 'getSelcted',
pure: false
})
#Injectable()
export class GetSelectedPipe implements PipeTransform {
transform(items: any[]): any {
// take out only selected values
return items.filter(item => item.selected === true);
}
}
Usage
{{(datas: getSelcted)?.length || 0}}
Note: Make sure GetSelectedPipe has been injected in declarations of AppModule's #NgModule declartions array.