Me loading an external script in a project in angular, through the file angular.json
"scripts": [
"src/assets/js/mask.js"
],
It is a script to apply a mask to some form fields. When the page is first loaded the script works, if I navigate to another page without refreshing and go back to the page containing the form it no longer works.
Is there another way to load this script whenever that component is accessed?
Remembering that the site works as a SPA (Single Page Application), so navigation between pages occurs without the need for new requests.
There are several masks, I run them through a function, see:
function id(el) {
return document.getElementById(el);
}
window.onload = function() {
id('nome')?.addEventListener("keyup", function() {
inicialMaiuscula(this);
});
id('telefone')?.addEventListener("keyup", function() {
mascara(this, mtel);
});
id('celular')?.addEventListener("keyup", function() {
mascara(this, mtel);
});
id('cep')?.addEventListener("keyup", function() {
mascara(this, cepm);
});
id('cep')?.addEventListener("change", function() {
getEndereco(this);
});
id('cpf')?.addEventListener("keyup", function() {
mascara(this, cpf_mask);
});
id('cpf')?.addEventListener("blur", function() {
validarCPF(this.value);
});
id('cpf')?.addEventListener("paste", function() {
return false;
});
id('rg')?.addEventListener("keyup", function() {
mascara(this, soNumeros);
});
id('nascimento')?.addEventListener("keyup", function() {
mascara(this, data);
});
id('usuario')?.addEventListener("keyup", function() {
letrasNumeros(event);
});
id('senha')?.addEventListener("blur", function() {
validaSenha(this);
});
id('confSenha')?.addEventListener("blur", function() {
validaSenha(this);
});
id('estado')?.addEventListener("input", function() {
tudoMaiuscula(event);
});
}
Full mask.js: https://jsfiddle.net/m50o6fn8/
CodePudding user response:
Lets first understand, why does it work in the beginning?
The way JS/jQuery code would work is, your script is getting into action after DOM Ready
(DOMContentLoaded). Suppose you've written a line $('input[mask]').mask(...)
to apply masking. So when this line executes, it queries, and finds elements that match the selector, and applies the mask
function to them. That's why it worked at page load.
Why did it not work later?
Of course, as we have seen, the script already ran. Its an SPA. So the static script resource you mentioned in angular.json
's scripts
option. It loads once on page load, so the next page visit won't re-execute or download the script. Cool.
How to make it work?
The most recommended way here is using Angular Directive. WHY? because we wanted to add behavior(masking) on top of the DOM. Excellent. So what happens is when you write a directive, you will be mentioning the selector like input[mask]
, so angular make sure that whenever any content is loaded on pages. and it matches the selector, it applies the behavior return inside directive class.
Simple Example
@Directive({
selector: 'input[mask]',
})
export class MaskInputDirective {
constructor(private el: ElementRef) {}
@Input() format = 'dd/mm/yyyy';
ngAfterViewInit() {
$(this.el.nativeElement).mask(this.format);
}
}
An interesting fact to note in directive is ngAfterViewInit
lifecycle hook should be used to get hold of elements it is acting upon. And you can easily get hold of element
by asking for dependency
inside constructor
like private el: ElementRef
But why re-invent the wheel? when things are already in a place. I would recommend you to use ngx-mask
npm library instead.
CodePudding user response:
First, you should find out the code snippet that is applying the mask to the form field from mask.js file. It should look like $('input').mask(...)
.
And then you should add that code snippet to OnInit
or AfterContentInit
lifecycle of each component you want to use it.
Btw it would be better to use a npm library instead of JS assets, i.e. https://www.npmjs.com/package/ngx-mask