In Html:
<input class="form-control"[(ngModel)]="value" #muInput/>
<button (click)="onSetAttribute()"> set</button>`
In this:
`#ViewChild('muInput') muInput: ElementRef; `
public seperator : string onSetAttribute() { if(this.seperator ) {
this.muInput.nativeElement.setAttribute('mask' , this.seperator); this.muInput.nativeElement.setAttribute('thousandSeparator' , ',');`
}}
I want to click on the button set a mask attribute to input this my code but is not working
You can do something like this :
<input class="form-control"[(ngModel)]="value" #muInput [attr.mask]="mask" />
<button (click)="changeMask()"> set</button>
In your component ts file, you should declare a class attribute mask, give it default value of w/e you want then:
changeMask() { this.mask = 'separator.2' // w/e value }
same thing for thousandSeparator attribute.
import { Renderer2 } from '#angular/core';
Use Renderer2 setattribute function
constructor ( private _renderer: Renderer2) { }
onSetAttribute() {
this._renderer.setAttribute(this.muInput.nativeElement,'mask' , 'separator.2');
this._renderer.setAttribute(this.muInput.nativeElement,'thousandSeparator' , ',');
}
Related
I have a directive that is used on input fields on my form. I am trying to get the value from that directive in my TS file
Directive
#Directive({
selector: '[appOskInput]',
})
export class OskInputDirective implements OnInit {
private isBlurTrue: boolean = false;
#HostListener('focus')
private onFocus() {
console.log("focus");
this.isBlurTrue = false;
this.keyboard.fireKeyboardRequested(true);
this.subscribeToKeyboardEvents();
}
#HostListener("onBlur")
private onBlur() {
console.log("blur");
this.isBlurTrue = true;
this.keyboard.fireKeyboardRequested(false);
this.unsubscribeFromKeyboardEvents();
}
}
HTML
<cb-form [formGroup]="setupForm">
<form-input
appOskInput
(inputChanged)="onInputChanged($event,'accountNumber')"
[formStatus]="formStatus"
[parentFormGroup]="setupForm"
[data]="{formControlName: 'accountNumber', name: 'accountNumber'}">
</form-input>
</cb-form>
Essentially I want to use the isBlurTrue value in my TS file. Anyone knows how I can do this?
I figured it out
I just passed an output event in the directive
#Output() blurChanged = new EventEmitter();
Then emitted the value to it
this.blurChanged.emit(this.isBlurTrue);
In my HTML
I added
(blurChanged)="onBlurChanged($event)"
And in my TS I added
onBlurChanged(ev) {
console.log(ev)
}
You could also have a public function within your directive where exposes your private property, and then use it in your template html from a parent control like this:
Directive
...
private isBlurTrue: boolean = false;
getBlur(): boolean {
return this.isBlurTrue;
}
HTML
<div #myDirective="appOskInput">
...
<input (blur)="myDirective.getBlur()"/>
...
</div>
I'm trying to limit the number of characters on an input using primeng 12, the maxlength property doesn't seem to work with this password component, on a normal input works fine but I need the special features like a template of password strength, what can I do?
<p-password [style]="{'width':'100%'}" [pKeyFilter]="blockSpace" [inputStyle]="{'width':'100%'}" placeholder="ContraseƱa" formControlName="password" maxlength='16' [feedback]="false"></p-password>
On a regular input the max length prevents typing more than 16 characters but with p-password users cant type infinite characters
Really late answer but as the issue is still there on primeng 13. Here below the solution I have implemented to add the functionality. I'm using a directive. Hope it helps
import {
AfterContentChecked,
Directive,
ElementRef,
Input
} from '#angular/core';
#Directive({
selector: '[compPasswordMaxLength]',
})
export class CompPasswordMaxLengthDirective
implements AfterContentChecked {
#Input('compPasswordMaxLength') length: number;
private domElement: HTMLElement;
constructor( private elementRef: ElementRef) {
// get ref HTML element
this.domElement = this.elementRef.nativeElement as HTMLElement;
}
public ngAfterContentChecked(): void {
const input = this.domElement.getElementsByTagName('input');
if (input && input.length > 0) {
(input[0] as HTMLElement).setAttribute('maxlength', this.length.toString());
}
}
}
Usage:
<p-password formControlName="password" [compPasswordMaxLength]="maxLength_Password">
</p-password>
I have a code:
document.getElementById('loginInput').value = '123';
But while compiling the code I receive following error:
Property value does not exist on type HTMLElement.
I have declared a var: value: string;.
How can I avoid this error?
Thank you.
if you want to set value than you can do the same in some function on click or on some event fire.
also you can get value using ViewChild using local variable like this
<input type='text' id='loginInput' #abc/>
and get value like this
this.abc.nativeElement.value
here is working example
Update
okay got it , you have to use ngAfterViewInit method of angualr2 for the same like this
ngAfterViewInit(){
document.getElementById('loginInput').value = '123344565';
}
ngAfterViewInit will not throw any error because it will render after template loading
(<HTMLInputElement>document.getElementById('loginInput')).value = '123';
Angular cannot take HTML elements directly thereby you need to specify the element type by binding the above generic to it.
UPDATE::
This can also be done using ViewChild with #localvariable as shown here, as mentioned in here
<textarea #someVar id="tasknote"
name="tasknote"
[(ngModel)]="taskNote"
placeholder="{{ notePlaceholder }}"
style="background-color: pink"
(blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }}
</textarea>
import {ElementRef,Renderer2} from '#angular/core';
#ViewChild('someVar') el:ElementRef;
constructor(private rd: Renderer2) {}
ngAfterViewInit() {
console.log(this.rd);
this.el.nativeElement.focus(); //<<<=====same as oldest way
}
A different approach, i.e: You could just do it 'the Angular way' and use ngModel and skip document.getElementById('loginInput').value = '123'; altogether. Instead:
<input type="text" [(ngModel)]="username"/>
<input type="text" [(ngModel)]="password"/>
and in your component you give these values:
username: 'whatever'
password: 'whatever'
this will preset the username and password upon navigating to page.
Complate Angular Way ( Set/Get value by Id ):
// In Html tag
<button (click) ="setValue()">Set Value</button>
<input type="text" #userNameId />
// In component .ts File
export class testUserClass {
#ViewChild('userNameId') userNameId: ElementRef;
ngAfterViewInit(){
console.log(this.userNameId.nativeElement.value );
}
setValue(){
this.userNameId.nativeElement.value = "Sample user Name";
}
}
I am trying to get the date pipe I'm using in my Angular app to parse out correctly when using it in the template within an input. Initially, before formatting the date, the code looked like this:
<input class="app-input" [readonly]="!hasAdminAccess"
[(ngModel)]="staff.profile.hireDate" placeholder="None"
[field-status]="getPropertyStatus('profile.hireDate')"/>
The closest I've gotten with the date pipe is this:
<input class="app-input"
{{ staff.profile.hireDate | date:'shortDate' }} placeholder="None"
[field-status]="getPropertyStatus('profile.hireDate')"/>
But what that prints to the view is this (literally this):
> <input class="app-input" 3/18/2014 placeholder="None"
> [field-status]="getPropertyStatus('profile.hireDate')"/>
Now, you'll notice that the correctly formatted date is there (and the date transformation is happening successfully, to make it this:
3/18/2014
However, I don't want the rest (obviously). How can I rework the syntax here so as to get just the date to print? I've stared at it and tried a few tweaks, but as of yet haven't been able to get it to work.
You can use the get and set functions in typescript and ngModelChanged property to modify the ngModel after it has been set.
Component Template :
<input class="app-input" [(ngModel)]="hireDate" (ngModelChange)="dateChanged($event)"/>
Component Class :
import { Component } from '#angular/core';
import { DatePipe } from '#angular/common';
#Component({
selector: 'my-app',
template: `
<div>
<button (click)="setDate()">Set Date</button>
<input class="app-input" readonly="true" [(ngModel)]="hireDate" (ngModelChange)="dateChanged($event)" placeholder="None"/>
</div>
`,
})
export class App {
name:string;
staff: any;
myDate: any;
private _hireDate;
dateChanged(value) {
this.hireDate = this.datePipe.transform(value, 'shortDate');
}
set hireDate(value) {
this._hireDate = this.datePipe.transform(value, 'shortDate');
}
get hireDate() {
return this._hireDate;
}
setDate() {
this.hireDate = '10-03-1993';
}
constructor(private datePipe: DatePipe) {
}
}
The value of the input will be set whenever the input changes, so it might cause a UX issue, as the user would not be able to enter his prefered date. A workaround would be to call the date changed function whenever the user has entered his date. (For eg. via a button click).
I believe the set and get functions work only for class variables, in your case you have a object property. Modifying the set function as shown below would work.
set hireDate(value) {
this._hireDate = this.datePipe.transform(value, 'shortDate');
this.staff.profile.hireDate = this._hireDate;
}
I have also added a plunkr here.
As the code provided bellow. I tried to select a dynamic element generated by ngIf but failed.
I used two ways in total.
ElementRef and querySelector
component template:
`<div class="test" *ngIf="expr">
<a id="button">Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a id="button">Value 2</a>
</div>`
component class:
expr: boolean;
constructor(
private elementRef: ElementRef,
) {
}
ngOnInit(): void{
//Call Ajax and set the value of this.expr based on the callback;
//if expr == true, then show text Value 1;
//if expr == false, then show text Value 2;
}
ngAfterViewInit(): void{
console.log(this.elementRef.nativeElement.querySelector('#button'));
}
The output result is null.
#ViewChild
component template:
`<div class="test" *ngIf="expr">
<a #button>Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a #button>Value 2</a>
</div>`
component class:
#ViewChild('button') button: elementRef;
expr: boolean;
ngOnInit(): void{
//Call Ajax and set the value of this.expr based on the callback;
//if expr == true, then show text Value 1;
//if expr == false, then show text Value 2;
}
ngAfterViewInit(): void{
console.log(this.button);
}
The out put result is undefined;
Is there a way to get dynamic dom generated by *ngIf?
Finally the problem has been solved through #ViewChildren.
And to log the updated result, it is necessary to use a separate function.
For example:
Wrong Code:
#ViewChildren('button') buttons: ElementRef;
function(): void{
this.expr = true; // Change expression then the DOM will be changed;
console.log(this.buttons.toArray()); // This is wrong because you will still get the old result;
}
Right Code:
#ViewChildren('button') buttons: ElementRef;
function(): void{
this.expr = true; // Change expression then the DOM will be changed;
}
ngAfterViewInit(): void{
this.buttons.changes.subscribe( e => console.log(this.buttons.toArray()) ); // This is right and you will get the latest result;
}
You can't get the element when the *ngIf="expr" expression is false because then the element doesn't exist.
The value is not yet set in ngOnInit(), only when ngAfterViewInit() is called.
Plunker example
#Component({
selector: 'my-app',
template: `
<div class="test" *ngIf="prop">
<a #button id="button1">button1</a>
</div>
<div class="test" *ngIf="!boolean">
<a id="button2">button2</a>
</div>`
,
})
export class App {
#ViewChild('button') button: ElementRef;
prop:boolean = true;
ngAfterViewInit() {
console.log(this.button);
}
}
Plunker example with ViewChildren
#Component({
selector: 'my-app',
template: `
<button (click)="prop = !prop">toggle</button>
<div class="test" *ngIf="prop">
<a #button id="button1">button1</a>
</div>
<div class="test" *ngIf="!boolean">
<a #button id="button2">button2</a>
</div>`
,
})
export class App {
#ViewChildren('button') button: QueryList<ElementRef>;
prop:boolean = true;
ngAfterViewInit() {
console.log(this.button.toArray());
this.button.changes.subscribe(val => {
console.log(this.button.toArray());
});
}
}
Is not exactly the best but I deal with a similar situation using [ngClass] instead *ngIf.
Just create a class with "display: none" and hide the elements when needed. The elements selected with #ViewChild can be accessed without problem.
For now you can use this little "hack" while search for a better solution or more elegant one.
ex.
.hide-element{
display: none;
}
<div class="test" [ngClass]="expr === 'yourTest' ? 'hide-element' : null">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
if you are handling some async return you can just use async pipe
<div class="test" [ngClass]="(expr | async) === 'yourTest' ? 'hide-element' : null">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
Hope it helps.
If you need the element only in the moment that someone interacts with it (e.g. clicks on it) or with a sibling or child element of it you can pass it's reference with the event.
Template:
<div class="test" *ngIf="expr">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
Code:
onButton1(button: HTMLButtonElement) {
}
If you need the element without interaction with it you might also look at the ViewChildren query instead of ViewChild.
You can set it up with
#ViewChildren('button') buttons: QueryList<ElementRef>;
You can then subscribe to changes of elements that match a selector through this.buttons.changes.subscribe(...). If the element get's created or deleted you will get notified through the subscription. However my first way involves far less boilerplate code.
Alternativly you can also only access the QueryList synchronously in moments where you are sure that the element exists (through some preconditions). In your example you should be able to retrieve the button with
let button: ElementRef = this.buttons.first;
in these cases.
<div class="test" *ngIf="boolean">
<a #button id="button1">button1</a>
</div>
#ViewChild('button') button: elementRef;
console.log(this.button);
the ID = 'button1', not 'button'?
var target = document.getElementById('Button1');