I want to print the value of textbox when i click of button. But it throws nullpointerexception. I also need to keep some value in the textbox i dont understand why?. Whatever i type in textbox and when i click on buttom i need to print the value of textbox What is the issue?
Below is my code:
ts file
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-mypage',
templateUrl: './mypage.component.html',
styleUrls: ['./mypage.component.scss']
})
export class mypageComponent implements OnInit {
constructor(private router: Router) {
}
ngOnInit() {
}
myFunc() {
var num1 = ((document.getElementById("exchageRateDate") as HTMLInputElement).value);
console.log(num1);
}
}
HTML File
<br>Welcome.<br>
Place - <input type="text" value="Sydney" ng-model="placeId" />
<button (click)="myFunc(placeId)" formtarget="_blank">Test</button>
Error:
ERROR TypeError: Cannot read property 'value' of null
Seems like you forgot to add id in input field
<input id="exchageRateDate" type="text" value="Sydney" ng-model="placeId" />
Edit: Angular way to do it
As you are using Angular so I will suggest you a better way to do this using NgModel
Try this
<br>Welcome.<br>
Place - <input type="text" value="Sydney" [(ngModel)]="placeId" />
<button (click)="myFunc(placeId)" formtarget="_blank">Test</button>
In component:
myFunc(num1) {
console.log(num1);//here you will get input value through ng-model
}
You need to set id of input tag remove ng-model because it's a angularjs(1.x.x) not angular(2/4/5/6/7/8)
In html
<br>Welcome.<br>
Place - <input id="exchageRateDate" type="text" value="Sydney" />
<button (click)="myFunc()" formtarget="_blank">Test</button>
In typescript:
myFunc() {
var num1 = ((document.getElementById("exchageRateDate") as HTMLInputElement).value);
console.log(num1);
}
Here is working example: Get value of input tag using HTMLInputElement
<input type="text" class="textbox" id="Summary" name="Summary"placeholder="Summary" value="{{Item.summary}}">
(document.getElementById("Summary") as HTMLInputElement).value;
Related
im making some register pages in a Ionic-Angular project, and i use some buttons to go to the next requisites to register. For example: first I ask for email, and until email format isnt't correct, my button to go to next page is disabled. When correct I enable it and go to a page where your name is asked. Here when the user enters his name, my code sets disabled atribute of the button to false, but the button stays as it was. As if i cant access the disable attribute. But when i reload the page in my browser, that same button does what i say in the code (disable = false).
This is very strange for me, how can the same code I used in the page before for the button disable work, but in the next page when I navigate by url to that next page not work. But that button on the page does work when reloaded in browser.
I´ve been thinking it could be something of angular lifecycle of the view|page|component.
I leave my code here, but i really think its just fine, and its doms or angulars fault.
HTML:
<div class="content" id="body">
<p class="titulo">Mi nombre es</p>
<ion-input
id="ionInput"
class="input"
inputmode="text"
maxlength="25"
minlength="2"
mode="ios"
pattern="text"
required="true"
type="text"
(ionChange)="inputValueChange($event)"
></ion-input>
<ion-button
disabled
id="continueButton"
(click)="navigateForward()"
expand="block"
fill="solid"
shape="round"
class="buttonContinue"
>Continuar</ion-button
>
</div>
Dont really take in count the CSS classes i remove or add. It has nothing to do with the problem.
.ts FILE:
export class Step2NamePage implements OnInit {
name = '';
continueButton: HTMLButtonElement;
constructor(private router: Router) {}
ngOnInit() {
}
inputValueChange(ev) {
const input = document.getElementById('ionInput');
const continueButton = document.getElementById('continueButton') as HTMLButtonElement
this.name = ev.detail.value;
// console.log(this.name);
if (this.name.length > 2) {
if (input.classList.contains('input')) {
(document.getElementById('continueButton') as HTMLButtonElement).disabled = false;
console.log('lo desbloque');
console.log(input, this.continueButton);
input.classList.remove('input');
input.classList.add('inputFull');
}
} else {
if (input.classList.contains('inputFull')) {
input.classList.remove('inputFull');
input.classList.add('input');
(document.getElementById('continueButton') as HTMLButtonElement).disabled = true;
console.log(input, this.continueButton);
}
}
}
navigateForward() {
this.router.navigate(['/register/step3-birthday']);
}
}
Angular keeps track of the DOM in it's own special way, and provides
ample ways for you to access element properties, values etc. You
shouldn't hardly ever be trying to find elements with
document.getElementById and the like...
Use ngModel (import the forms module - see this post) to track and utilize form input values
Use ngClass to have the DOM update classes for elements on the fly - see this post
export class Step2NamePage implements OnInit {
name = '';
continueButton: HTMLButtonElement;
constructor(private router: Router) {}
ngOnInit() {}
navigateForward() {
this.router.navigate(['/register/step3-birthday']);
}
}
<div class="content" id="body">
<p class="titulo">Mi nombre es</p>
<ion-input
id="ionInput"
*ngClass="{'inputFull':name.length>2, 'input': name.length<=2}"
[(ngModel)]="name"
inputmode="text"
maxlength="25"
minlength="2"
mode="ios"
pattern="text"
required="true"
type="text"
></ion-input>
<ion-button
[disabled]="name.length<=2"
id="continueButton"
(click)="navigateForward()"
expand="block"
fill="solid"
shape="round"
class="buttonContinue"
>Continuar</ion-button>
</div>
I need to update the angular model on a js change event,
this is a simplified, isolated demo:
hero-form.component.html:
<button type="button" id='btn1'>change</button>
<input type="text" id="txt1" name="txt1" [(ngModel)]="str1" />{{str1}}
hero-form.component.ts:
...
import * as $ from "jquery";
...
export class HeroFormComponent implements OnInit {
str1 = "initval";
ngAfterViewInit(){
var txt1 = $('#txt1');
$('#btn1').on('click', function(){
txt1.val('new val').change();
// when js/jquery triggers a change on the input, I need the str1
// which was bound using [(ngModel)] to be updated
});
}
when clicking the button the value of the textbox changes to new val but the interpolation {{str1}} is not affected, however if I change the value of the textbox manually it works.
is it possible to update the model bound with ngmodel on a js change event ?
In angular project we should not implement your requirement like your way.
You can use (click) event and #txt1 to get value
In ts component implement change str1 value.
export class AppComponent {
name = 'Binding data in Angular';
str1 = "initval";
ngAfterViewInit() {
}
change(val) {
console.log(val)
this.str1 = val;
}
}
Updated HTML
<hello name="{{ name }}"></hello>
<button type="button" id='btn1' (click)="change(txt1.value)">change</button>
<input type="text" #txt1 id="txt1" name="txt1" />{{str1}}
Demo: https://stackblitz.com/edit/angular-click-change-value
I have a text field in an component, that when in focus, needs to populate a hidden field outside of the component that is nearest to it.
At the moment I can get the field in focus, but what I need to do now is populate the hidden field.
Here is what I have so far:
HTML:
<h2>Test</h2>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
App-Focus:
<p>
focus works!
<input id="inputId" type="text" name="" value="">
</p>
Component:
ngAfterViewInit(){
setTimeout(()=>{
let dummyEl = this.elRef.nativeElement.querySelectorAll("#inputId")
for(let i = 0; i < dummyEl.length; i++){
let el = dummyEl[i]
// if (document.activeElement === el){ stops working if I use this
console.log(document.activeElement === el)
console.log(el.closest("#h0"))//always returns null
// }
}
}, 3000)
}
closest searches direct descendants but not siblings of the descendants e.g.
<div>
<input id="#h0">
<app-root>
<p>
<input id="#inputId">
</p>
</app-root>
</div>
In this HTML, calling closest from the #inputId element will only find the div, not the input because it is not a direct descendant - it is a child of div.
You need to modify your html so app-root and #h0 are wrapped by a div. You can then find the closest div and select the child of that element e.g.
ngAfterViewInit() {
setTimeout(() => {
let dummyEl = this.elRef.nativeElement.querySelectorAll('#inputId');
for(let i = 0; i < dummyEl.length; i++) {
let el = dummyEl[i];
let div = el.closest('div');
if(div !== null) {
console.log(div.querySelector('#h0'));
}
}
}, 3000);
}
}
Also you id's must be unique so using #h0 for each input is invalid HTML. You might be better using a class if you want to find the elements with the same "tag" e.g.
<input class="h0" ... >
If you need to pass data from the AppFocusComponent, you could use Angular Event Emitters. The example in the documentation emits null in the $event but other data, both primitive and Objects, can be passed as well.
Here is a link to an example on Stack Blitz
app-focus.component.ts
First, set up an EventEmitter in the AppFocusComponent. The data can be emitted in an Angular Lifecycle Hook. Or can be bound to a User Input Event.
import { AfterViewInit, Component, EventEmitter, Input, Output } from
'#angular/core';
#Component({
selector: 'app-focus',
templateUrl: './app-focus.component.html'
})
export class AppFocusComponent implements AfterViewInit {
#Input() data: any = null;
#Output() focus = new EventEmitter();
ngAfterViewInit() {
setTimeout(()=>{
this.focus.emit(this.data);
}, 3000)
}
onFocus(event: Event) {
console.log(event);
this.focus.emit(this.data);
}
}
app-focus.component.html
Next, bind the focus event on the input to the onFocus() method in the component. Here, ngModel is used to bind the data that is emitted when the onFocus($event) method fires. This can either be from user input, or the data can be passed in via an #Input(). I wasn't sure where the data is coming from, so there a couple of approaches in the example.
<p>
<input type="text" (focus)="onFocus()" [(ngModel)]="data">
</p>
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
h0Value: string = '';
h1Value: string = '';
h2Value: string = '';
h3Value: string = '';
// an alternate way to set the value instead of setting it in the template
setH1Value(event: any) {
this.h1Value = event;
}
}
app.component.html
Lastly, bind the [value] of the <input>s to their respective properties and have the AppComponent listen to the (focus) event from the AppFocusComponent. The data that comes from the AppFocusComponent can be assigned directly in the template. (focus)="h0Value = $event". Or it can be wrapped in a method on the component while passing the $event through. (focus)="setH1Value($event)". If the data is being initialized via data from an API or some other source, it can be passed in via the #Input. data="h2 data".
The labels here are used for demonstration purposes so the data that's emitted by the AppFocusComponent can be viewed in the UI.
<h2>Test</h2>
<label>{{ h0Value }}</label>
<input type="hidden" id="h0" name="" [value]="h0Value">
<app-focus (focus)="h0Value = $event"></app-focus>
<label>{{ h1Value }}</label>
<input type="hidden" id="h1" name="" [value]="h1Value">
<app-focus (focus)="setH1Value($event)"></app-focus>
<label>{{ h2Value }}</label>
<input type="hidden" id="h2" name="" [value]="h2Value">
<app-focus data="h2 data" (focus)="h2Value = $event"></app-focus>
<label>{{ h3Value }}</label>
<input type="hidden" id="h3" name="" [value]="h3Value">
<app-focus (focus)="h3Value = $event"></app-focus>
In my Angular 4 application I have this input box in which I ONLY want numbers... 0-9 to be entered.. otherwise I want it to clear out onkeyup
HTML
<input type="number" (keyup)="numbersOnly($event)" placeholder="0000000000" formControlName="phone" maxlength="10"/>
Above works to call this function in the component
but it is not working to prevent letters.
numbersOnly(val) {
let y = this.trackerForm.controls['phone'].value
y.value = y.value.replace(/[^0-9.-]/g, '');
console.log('y', y);
}
Is .value the wrong approach?
Should I be using event preventdefault?
The console log for 'y' shows correctly.
What do I need to do?
Since you are using ReactiveForm, you should understand that FormConrtol's value only has a getter.
If you want to change formControl's value, use patchValue or setValue.
let y = this.trackerForm.controls['phone'];
this.trackerForm.controls['phone'].patchValue(y.value.replace(/[^0-9.-]/g, ''));
// OR
this.trackerForm.controls['phone'].setValue(y.value.replace(/[^0-9.-]/g, ''));
Refer demo.
You should probably have a model on the input and pass that into your function with the event. Change the model instead of the event value. Also your solution may not be working because the input probably has the value updated on the (keypress) event.
let y = this.trackerForm.controls['phone'].value
^^^^^
y.value = y.value.replace(/[^0-9.-]/g, '');
^^^^
You are already taking the value.
Change it to
let y = this.trackerForm.controls['phone'];
y.value = y.value.replace(/[^0-9.-]/g, '');
You use ngModel instead.
<input type="number" (keyup)="numbersOnly()" placeholder="0000000000" formControlName="phone" maxlength="10" [(ngModel)]="value"/>
value = "";
numbersOnly() {
this.value = this.value.replace(/[^0-9.-]/g, '');
}
To access the value of the input field, use ngModel (documentation)
For form validation, have a look at the built-in tools. If you use these, you can simply use the HTML attribute pattern to achieve a validation of an input field by a regular expression. (documentation)
Updated code:
<input type="number" name="phoneNumber" placeholder="0000000000" pattern="[0-9.-]*" maxlength="10" [(ngModel)]="phoneNumber" #phoneNumber="ngModel"/>
Please note that you need to define a new field named phoneNumber in your component.
For this kind of things angular has directives that listen to the events coming from components.
If you have your input mapped to a model then the way you assign the value will not be reflected into model. So that should be taken care of as well.
#Directive({
selector: '[restrict]',
})
export class RestrictDirective {
constructor(private control: NgControl) {}
#HostListener('keyup', ['$event.target'])
#HostListener('paste', ['$event.target'])
private onInputEvent(input) {
if (input.value) {
let truncated = input.value.replace(PATTERN, ''); //put your pattern here
// change value only if it contains disallowed characters
if (truncated !== input.value) {
this.control.valueAccessor.writeValue(truncated); //write to model
this.control.viewToModelUpdate(truncated); //write to view
}
}
}
}
Then just get to use the directive in the input
<input type="text" restrict/>
For integers the pattern would be
const PATTERN = /[\D]/g;
Improving Damask's answer. If we are using Reactive Forms, I's necesary the last line: "this.control.control.setValue(truncated); "
<input type="text" [restrict]="'[^0-9]'" />
The directive
#Directive({
selector: '[restrict]',
})
export class RestrictDirective {
regexp:any;
#Input('restrict')
set pattern(value)
{
this.regexp=new RegExp(value,"g");
}
constructor(private control: NgControl) {}
#HostListener('input', ['$event.target'])
#HostListener('paste', ['$event.target'])
private onInputEvent(input) {
if (input.value) {
let truncated = input.value.replace(this.regexp, '');
if (truncated !== input.value) {
this.control.valueAccessor.writeValue(truncated); //write to model
this.control.viewToModelUpdate(truncated); //write to view
this.control.control.setValue(truncated); //send to control
}
}
}
}
create a simple directive something like this
import { Directive, HostListener } from '#angular/core';
#Directive({
selector: '[appNumberOnly]'
})
export class NumberOnlyDirective {
constructor() { }
#HostListener('keypress', ['$event'])
onInput(event: any) {
const pattern = /[0-9]/;
const inputChar = String.fromCharCode(event.which ? event.which : event.keyCode);
if (!pattern.test(inputChar)) {
event.preventDefault();
return false;
}
return true;
}
}
import this in your module
and in HTML
<input type="number" appNumberOnly placeholder="0000000000" formControlName="phone" maxlength="10"/>
Also inside your component.ts, inside formBuilder you can have something like this
phone: ['', Validators.compose([Validators.maxLength(10), Validators.pattern('[6-9]\\d{9}'), Validators.required])],
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";
}
}