how to change labeltext inside template in Angular 4 - html

I am having a angular component here is my component
#Component({
selector: 'labelnumeric',
template: '<label>hello</label>'
})
here in template i am using hello as label text
and here component is defining in HTML control
here is my HTML
<labedate></labedate>
so on the basis of HTML control i want to change the label text how can i done this ?
is there is any possibility to set the name based on attributes ?

What you are looking for is #Input in your component
See the documentation here:
https://angular.io/guide/component-interaction
What you basically need todo is to import Input and then define an input property in your component
#Component({
selector: 'labelnumeric',
template: '<label>{{something}}</label>'
})
export class XYZ {
#Input() something: string;
}
and then you can use this like so in the html part
<labelnumeric [something]= "Text"></labelnumeric>

I think all you need is #input
#Component({
selector: 'labelnumeric',
template: `<label>{{numeric}}</label>`,
})
export class HelloComponent {
#Input() numeric: string;
}
Then use it like :
<labelnumeric numeric='10'></labelnumeric>
//OR
<labelnumeric [numeric]='your_varible'></labelnumeric>
WORKING DEMO (Basic Working demo of #input)

Related

How to pass Angular directive by reference?

In an existing component template I have this (simplified) element:
<input type="button" #refreshPrice />
This is picked up (I don't know the correct term) by this property so we can subscribe to it's click event and call a function when the input element is clicked.
I want to replace this input element with a component I've developed, which would make it look (simplified) like this:
<spinner-button #refreshPrice></spinner-button>
This child component has this as its (simplified) template:
<button>
<mat-spinner></mat-spinner>
</button>
So now the button element, in the child component template, needs to have the #refreshPrice hash attribute (?) attached.
To do this, perhaps the spinner-button element should take the name of the hash attribute as an attribute value. Here is the complete spinner component class file:
import { Component, Input, OnInit } from "#angular/core";
#Component({
selector: "spinner-button",
templateUrl: "./spinner-button.component.html",
styleUrls: ["./spinner-button.component.css"]
})
export class SpinnerButtonComponent implements OnInit {
constructor() {}
#Input() targetElement: string;
ngOnInit() {
}
}
In theory, the targetElement property can then be attached to the button element as a hash attribute - but how is this done?
the #Input() attribute here allows you to bind a value to a variable on your component, if you want to have the parent do something based on your components data, you might want to use #Output() and emit a custom event. If the requirement is just listen to a click event then adding a (click)=functionToBeCalled() should help your cause here.
You can refer to the official docs as well:
https://angular.io/guide/inputs-outputs

Host Binding rearranges applied classes

I am using #HostBinding('class') to inject classes into the host element. The classes to be injected are generated based on user-supplied parameters. The problem I ran into and I could not find anyone else experiencing is that the classes are applied in an order different from the way I expected them.
For example, having a component defined below:
import {Component, HostBinding, Input} from '#angular/core';
#Component({
selector: '[icon]',
template: `
<ng-content></ng-content>
`
})
export class SuiIconComponent {
#Input() iconType = '';
#HostBinding('class')
get classes(): string {
return [this.iconType, 'icon'].join((' '));
}
}
When I apply the component like shown below:
<div icon iconType="car"></div>
And inspect, I see <div class="icon car"></div> instead of the appropriately formatted <div class="car icon"></div>.
I have tried reversing the array before joining but that did not help either.
Is there any way I get the classes to get rendered in the proper order?
Edit: I realized the classes are being rearranged in alphabetic order.
I'm not sure why angular changes the order, but you can solve your problem with little bit of change in your template.
#Component({
selector: 'icon',
template: `
<div [ngClass]="iconType + ' icon'">
<ng-content></ng-content>
</div>
`
})
export class SuiIconComponent {
#Input() iconType = '';
}
and use it as follows
<icon iconType="car">
Some content here
</icon>

In Angular how do I dynamically wrap certain words in another html element?

I have this simple Angular Component:
#Component({
selector: 'my-component',
template: '<p>{{someString}}</p>',
})
export class MyComponent {
#Input() someString: string;
}
someString could be any string of any length. As an example, imagine that someString's value is :
"If you want my body and you think I'm sexy, come on, sugar, tell me so."
In that case the HTML generated by Angular would essentially be equivalent to:
<p>If you want my body and you think I'm sexy, come on, sugar, tell me so.</p>
How would I modify MyComponent so that it detects each occurrence of the word sexy in someString and have Angular wrap that word in another HTML element such as <b>. So in this example case it would generate something like:
<p>If you want my body and you think I'm <b>sexy</b>, come on, sugar, tell me so.</p>
What if I wanted to wrap every occurrence of the word sexy in an Angular Component instead of a native HTML Element? Would that necessitate a different approach?
You can try this :D
#Component({
selector: 'app-test',
template: `
<p [innerHTML]="stringFormatted()"></p>
`,
styles: []
})
export class TestComponent {
someString = "If you want my body and you think I'm sexy, come on, sugar, tell me so.";
stringFormatted() {
return this.someString.replace(/sexy/g, '<b>sexy</b>');
}
}
You can use the something like below - wherein after rendering the main sentence, you can replace the special word with a span element and apply a CSS class, say .special to that span tag.
import { Component, Input, ElementRef, AfterViewInit } from '#angular/core';
#Component({
selector: 'my-component',
template: '<p>{{sentence}}</p>'
})
export class MyComponent implements AfterViewInit {
#Input() sentence: string;
#Input() specialWord: string;
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
this.el.nativeElement.innerHTML = this.el.nativeElement.
innerHTML.replace(new RegExp(`${this.specialWord}`, 'g'),
`<span class="special">${this.specialWord}</span>`);
}
}
To keep your code generic, you can use additional #Input() for special word.
In your application's styles.scss, you can define the CSS class .special.
.special {
font-weight: bold;
}
If you wonder why you can't use similar logic to replace the content of sentence by something like below:
this.sentence = this.sentence.replace(new RegExp(`${this.specialWord}`, 'g'),
`<span class="special">${this.specialWord}</span>`);
then, note that Angular will escape the HTML tags and they will appear as is in the output. So you will see something like this in the browser, instead of styled spans.
Hello, it's a <span class="special">beautiful</span> day and I am in a very <span class="special">beautiful</span> city
That's why, I had to resort to manipulating the innerHTML so that replacement is done after Angular has rendered the sentence to DOM.
This solution avoids using innerHTML and relies strictly on Angular constructs.
#Component({
selector: 'my-component',
template: `
<p>
<ng-container *ngFor="let segment of segments">
<span *ngIf="!segment.shouldBeBold()">segment.text</span>
<b *ngIf="segment.shouldBeBold()">segment.text</b>
</ng-container>
</p>
`,
})
export class MyComponent {
#Input() someString: string;
private wordsToBold = new Set(['sexy', 'body', 'sugar']);
get segments() {
const regex = this.makeRegex();
const segments = this.someString.split(regex);
return segments.map(segment => {
return { text: segment, shouldBeBold: wordsToBold.has(segment.toLowerCase()) };
});
}
private makeRegex() {
const expression = [...this.wordsToBold].join('\\b|\\b');
return new RegExp(`(\\b${expression}\\b)+`, 'gi');
}
}

Angular 6 Failed to compile

Example:Tthis is a child component for app component, using command line
ng g c emp
to create it. what ever created it will fail at compile
time.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-emp',
templateUrl: `
<h2>EmpList</h2>
<ul *ngFor="let emp of empArr">
<li>{{emp.name}} {{emp.id}} {{emp.age}}</li>
</ul>
`,
styleUrls: ['']
})
export class EmpComponent implements OnInit {
public empArr=[
{"id":1,"name":"jamal","age":25},
{"id":2,"name":"yasser","age":80},
{"id":3,"name":"zolla","age":11}
];
constructor() { }
ngOnInit() {
}
}
I got below error message:
> Module not found: Error: Can't resolve './
> <h2>EmpList</h2>
> <ul *ngFor="let emp of empArr">
> <li>{{emp.name}} {{emp.id}} {{emp.age}}</li>
> </ul>
> ' in 'D:\Angular\bind\src\app\emp'
> ERROR in ./src/app/emp/emp.component.ts
> Module not found: Error: Can't resolve './' in 'D:\Angular\bind\src\app\emp'
Since you're providing an inline template, the templateUrl property in your component decorator should be called template instead.
Alternatively, put your template in a separate file, and then you can refer to it by URL.
You need to do changes in your emp.component.ts file.
Angular 6 provides template injection in 2 way.
By using templateUrl :
If you use templateUrl your code should look like :-
#Component({
selector: 'app-emp',
templateUrl: './emp.component.html',
styleUrls: ['']
})
Here you need to provide the link of external html file where you can put your html code.
I have created demo for this example.
By using template: If you use template only in your code, it should look like-
#Component({
selector: 'app-emp',
template:
<h2>EmpList</h2>
<ul *ngFor="let emp of empArr">
<li>{{emp.name}} {{emp.id}} {{emp.age}}</li>
</ul>
,
styleUrls: ['']
})
Please have a look for another demo using template selector.
I think it will clear idea and difference between templateUrl and template.
You are providing html into templateUrl ...
Basically from angular2 in #component constructor object have few properties for component.html linking
templateUrl : here we provide relative path of component.html
file.
template : here we provide html used in component.
so you can use anyone and provide input accordingly.

Template extensions during component extentions in Angular 5

Anular 5: For clear structure of module i wanna make some AbstractParentComponent (that have reusable logic and template) and have possibility extend it:
#Component({
selector: 'app-parent',
template: ' //reusable header element with logic
*here we should have ability to change part of tamplate*
<ng-container *ngTemplateOutlet="customTemplate"> </ng-container>
//reusable footer element with logic
'
})
export class ParentComponent{
//logic impl
And i wanna ability create extended components that extend all parent logic but implement own part with custom template:
#Component({
selector: 'app-child',
template: '
//here i wanna extend parent template
/*something like*/ <ng-template #customTemplate>
//some template impl
</ng-template>'
})
export class ChildComponent extends ParentComponent{}
How it's possible to do ?
How about:
#Component({
selector: 'app-child',
template: '<app-parent></app-parent>'
})
export class ChildComponent extends ParentComponent{}