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";
}
}
Related
How could i update a doc inside my firestore without precisely write in the code the field i want to update , cause already is reached through the form:
.Lets say the HTML tag in Angular already brings both the key and the import(that one to be updated):
HTML Tags
<form [formGroup]="importNgForm" (submit)="addUniqueImport()">
<div class="modal-body">
<div class="form-group">
<label for="key"></label>
<input disabled type="text" value='{{incomeSelected}}' name="key" class="form-control" formControlName="key" />
</div>
<div class="form-group">
<label for="import">Add amount</label>
<input type="number" name="import" class="form-control" formControlName="import" />
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Add</button>
</div>
......more code
Then on my component for that html :
some imports...
export class UserSheetBalanceComponent implements OnInit {
importNgForm: FormGroup;
constructor(
private service: Service,
private amountBuilder:FormBuilder,
) {
this.importNgForm = this.amountBuilder.group({
key:new FormControl(),
import:new FormControl(),
});
}
addUniqueImport() {
this.service.addingImport(this.importNgForm.value as addImport)
}
and then finally on my service component i just try to pass the parameters the form brings :
addingImport(dataToPass: addImport) {
const path = this.docCreator
.collection('users')
.doc(this.userdata.uid)
.collection('Incomings')
.doc(this.userdata.uid);=====>Path reaching the doc to update
Until declaring the path to access that document where the field is.But then when try to refer the name of the field i want to update through the form (dataToPass.key) ,and the import for this field im doing reference to (dataToPass.import) the error appears.
path.update({dataToPass.key:dataToPass.import}) ====>doesn't work
}
The problem is in the key, let say i instead of accessing my form(dataToPass) i write directly the name of the field to update(some name),i does work
path.update({some name:dataToPass.import}) ======>does work
}
so im wondering how could i access that field key without precisely write it , but dynamically, in order to update my import once the field on query matchs
Thanks in advance!!!!
if you have reference to object in firebase
const path = this.docCreator
.collection('users')
.doc(this.userdata.uid)
.collection('Incomings')
.doc(this.userdata.uid);
you can crete empty object and use key name from dataToPass.key to set property
let foo: any = {};
foo[`${dataToPass.key}`] = dataToPass.import;
path.update(foo);
My scenario as follows
1) When the user enters a keyword in a text field and clicks on the search icon it will initiate an HTTP request to get the data.
2)Data is rendered in HTML with ngFor
The problem is on the first click the data is not rendered in HTML but I am getting the HTTP response properly, and the data rendered only on second click.
component.ts
export class CommerceComponent implements OnInit {
private dealList = [];
//trigger on search icon click
startSearch(){
//http service call
this.getDeals();
}
getDeals(){
this.gatewayService.searchDeals(this.searchParams).subscribe(
(data:any)=>{
this.dealList = data.result;
console.log("Deal list",this.dealList);
},
(error)=>{
console.log("Error getting deal list",error);
this.dealList = [];
alert('No deals found');
}
);
}
}
Service.ts
searchDeals(data){
var fd = new FormData();
fd.append('token',this.cookieService.get('token'));
fd.append('search',data.keyword);
return this.http.post(config.url+'hyperledger/queryByParams',fd);
}
HTML
//this list render only on second click
<div class="deal1" *ngFor="let deal of dealList">
{{deal}}
</div>
UPDATE
click bind html code
<div class="search-input">
<input type="text" [(ngModel)]="searchParams.keyword" class="search" placeholder="" autofocus>
<div class="search-icon" (click)="startSearch()">
<img src="assets/images/search.png">
</div>
</div>
According to Angular official tutorial, you could have problems if you bind a private property to a template:
Angular only binds to public component properties.
Probably, setting the property dealList to public will solve the problem.
Remove "private" from your dealList variable. That declaration makes your component variable available only during compile time.
Another problem: you are implementing OnInit in yout component but you are not using ngOnInit. Angular is suposed to throw an error in this situation.
My suggestion is to switch to observable:
I marked my changes with CHANGE
component.ts
// CHANGE
import { Observable } from 'rxjs/Observable';
// MISSING IMPORT
import { of } from 'rxjs/observable/of';
export class CommerceComponent implements OnInit {
// CHANGE
private dealList: Observable<any[]>; // you should replace any with your object type, eg. string, User or whatever
//trigger on search icon click
startSearch() {
//http service call
this.getDeals();
}
getDeals() {
this.gatewayService.searchDeals(this.searchParams).subscribe(
(data:any)=>{
// CHANGE
this.dealList = of(data.result);
console.log("Deal list",this.dealList);
},
(error)=>{
console.log("Error getting deal list",error);
// CHANGE
this.dealList = of([]);
alert('No deals found');
}
);
}
}
HTML
<!-- CHANGE -->
<div class="deal1" *ngFor="let (deal | async) of dealList">
{{deal}}
</div>
Try this:
this.dealList = Object.assign({},data.result);
Better do this inside the service.
By default, the angular engine renders the view only when it recognizes a change in data.
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.
I have a simple input that I want to reset the value to empty string after I am adding hero. The problem is the value is not updated. why?
#Component({
selector: 'my-app',
template: `
<input type="text" [value]="name" #heroname />
<button (click)="addHero(heroname.value)">Add Hero!</button>
<ul>
<li *ngFor="let hero of heroes">
{{ hero.name }}
</li>
</ul>
`,
})
export class App {
name: string = '';
heroes = [];
addHero(name: string) {
this.heroes.push({name});
// After this code runs I expected the input to be empty
this.name = '';
}
}
You have one-way binding so when you're typing something in your input your name property isn't changed. It remains "". After clicking on Add hero! button you doesn't change it.
addHero(name: string) {
this.heroes.push({name}); // this.name at this line equals ''
this.name = ''; // it doesn't do any effect
}
Angular2 will update value property only if it is changed.
Use two-way binding which is provided by #angular/forms
[(ngModel)]="name"
to ensure that your name property will be changed after typing.
Another way is manually implementing changing
[value]="name" (change)="name = $event.target.value"
In Angular Template binding works with properties and events, not attributes. as per html attribute vs dom property documentation of angular so as you have used [value] binding its binding to attributes not to the property of that input and because of it value remain in it after you set this.name = "".
I'm trying to set a dynamic form in Angular2.
So, in my ngOnInit function, I made a Ajax request to get a JSON with form data.
Like this :
export class CustomerEditComponent{
private customer : Customer = new Customer();
private customerForm;
constructor(private _CustomersService: CustomersService, private _routeParams: RouteParams, private _fb: FormBuilder){
this.customerForm = _fb.group({
name: [],
job: [],
arrival_date: []
});
}
ngOnInit(){
let id = this._routeParams.get('id');
this._CustomersService.getById(id).subscribe(res => {
this.customer = res;
});
}
onSubmit(event){
console.log(event);
}
}
So, at the component construct, 'customer' is equals to a newest one. (all properties are empty). But just after, we set value to every properties.
No problem for that, my input has the correct values.
But, if I submit my form, the form value is equals to :
Object {name: null, job: null, arrival_date: null}
(But the form in the view is correctly populate).
Here my form (condensed) :
<form [ngFormModel]="customerForm" (ngSubmit)="onSubmit(customerForm.value)">
<input md-input [(value)]="customer.name">
<input md-input [(value)]="customer.job">
<input md-input type="date" [(value)]="customer.arrival_date">
<button type="submit">Save</button>
</form>
I use [(value)] cause ng2-material package. (I already try with ngControl).
I think my code is 'wrong' about this feature, but I dunno where.
Thanks !
EDIT :
I have found the answer !
With ng2-material, we need to set [(value)] and [(ngModel)] together on every input like this :
<form [ngFormModel]="customerForm" (ngSubmit)="onSubmit(customerForm)">
<input md-input [(value)]="customer.name" [(ngModel)]="customer.name">
<input md-input [(value)]="customer.job" [(ngModel)]="customer.job">
<input md-input type="date" [(value)]="customer.arrival_date" [(ngModel)]="customer.arrival_date">
<button type="submit">Save</button>
</form>
[(value)] is used by ng2-material to set the value 'on front'.
I think that the problem is that you didn't associate your form inputs with their controllers within the ngFormControl directive in your template. You should refactor that way:
<form [ngFormModel]="customerForm" (ngSubmit)="onSubmit(customerForm.value)">
<input md-input [(value)]="customer.name"
ngFormControl="name">
<input md-input [(value)]="customer.job"
ngFormControl="job">
<input md-input type="date" [(value)]="customer.arrival_date"
ngFormControl="arrival_date">
<button type="submit">Save</button>
</form>
See this link from ng2-material samples: https://github.com/justindujardin/ng2-material/blob/master/examples/components/input/form_builder.html
Otherwise why don't you use the customer object instead of the customerForm.value one?
Hope it helps you,
Thierry