StencilJs value does not exist on type 'Element' - html

I want to set the value of an ion-input field when the page is loaded.
I'm trying to get the element from the shadowDom using the shadowRoot querySelector.
It is a stencil project with ionic. The component uses the shadowDOM.
When I try to get the value my IDE says:
The nameEl:
const nameEl = this.el.shadowRoot.querySelector('#name');
The value will be set correctly, but I was wondering how I could fix this error message.
EDIT:
Answer as suggested by Ash is correct. And like Ash mentioned there are two ways of implementing this solution. But I was wondering if there is any difference between the solutions?
const nameEl = this.el.shadowRoot.querySelector('#name') as HTMLInputElement;
or
const nameEl: HTMLInputElement = this.el.shadowRoot.querySelector('#name');
EDIT:
The solution of course also work as one-liners as in Ash his example.
(this.el.shadowRoot.querySelector('#name') as HTMLInputElement).value
And in my case the input is a ionic input:
(this.el.shadowRoot.querySelector('#name') as HTMLIonInputElement).value

Setting the value works as you said but the reason for the error is as the message says Property 'value' does not exist on type 'Element'. To phrase it differently to help you understand, the message is saying:
You have something of type Element
The value property does not exist on the type definition for that something
Therefore you need to either correct the code to get the right type of element or in your case tell the code what to expect.
(<HTMLInputElement>nameEl).value
// OR
(nameEl as HTMLElement).value
The above snippets were taken from the related questions below and updated to match your variable names.
I answered here because you mentioned Stencil but is not related to the issues, however this question is a duplicate and answers for similar questions can be found at Property 'value' does not exist on type 'EventTarget' and Property 'value' does not exist on type EventTarget in TypeScript

Related

jQuery: Unable to set values of cloned input element and cannot copy disabled property

I'm having issues setting up new values to cloned input fields.
clonedElement = element.clone(true); //This is a whole DIV which has inputs in it.
I then search for the inputs and modify as needed.
var newValue = "New Value";
$(clonedElement).find("#"+id).val(newValue);
every time I try to set a value (before appending the clonedElement) I get the following error.
Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable
however, this works using the same process.
$(clonedElement).find("#"+id).val("");
Also, changing values to attributes such as the name also work as expected
vew newName = "new_name";
$(clonedElement).find("#"+id).attr("name", newName);
I can set a blank value and empty the fields but I cannot pass any actual values, neither coming from another variable or even hard-coded values, only blank works.
Another thing I noticed is that the "disabled" property is not getting copied along with the cloned inputs. All other attributes and properties do get copied.
Any ideas how to get new values added to cloned elements before appending the element to the document?
Thanks in advance,
I figured what the problem was. there is an input type file among all of the inputs and since I was looping all inputs to set the value without filtering some input types, the loop broke whenever it reached a select.
To fix the issue i simple did something like this.
var newValue = "my new value";
$("#"+newId+":not(input[type=file])", clonedElement).val(newValue);
$("#"+newId+":input[type=file]", clonedElement).text(newValue);
that's a workaround that worked for me and can easily be improved.

concatenate variables in angular property element

I comment, and looked here and I can not find the solution, my problem is the following:
in my html template in angular, I need to pass a series of data to the metadata property of a button, I can't get the correct way to successfully concatenate the variable that contains the value.
this should be the html element:
<mati-button clientId="clientId" flowId="flowId" color="green"metadata='{"user_id":"1234778","email":"som#som.com"}'/>
I tried several ways but I can't insert the respective values....
example:
<mati-button metadata='{"userID": "{{user.id}}" }'></mati-button>
unsuccessfully...
Assuming mati-button is an Angular component with metadata as Input(), you are probably looking for
<mati-button
[clientId]="clientId"
[flowId]="flowId"
[color]="green"
[metadata]="{ userId: '1234778', email: 'som#som.com'}"
></mati-button>
See the guide on property binding to learn more:
To bind to an element's property, enclose it in square brackets, [], which identifies the property as a target property. [...] The brackets, [], cause Angular to evaluate the right-hand side of the assignment as a dynamic expression. Without the brackets, Angular treats the right-hand side as a string literal and sets the property to that static value.
By "dynamic expression" they mean JS-expressions, i.e., a public variable available through the component's TypeScript, a boolean expression, an array, or, like in your case, a JS-object that you can construct inline.
You can try doing this
<mati-button metadata="{'userID': user.id }"></mati-button>
metadata='{" userID ": {{user.id}}}'
in the end I got it. Apparently I don't know why, but the third-party script hides that parameter and it couldn't be debugged in the console, but it does receive them without any problem! Thanks everyone for your help!

How to Retrieve Values from a Class Within a Class Using JavaScript

I am not experienced with HTML and 'JavaScript', and is having a roadblock when attempting to check the values from a class.
Below is the source as seen from F12
I would like to retrieve all createdby text -muted values (as they may contain more than one row) to check if any of them matches SYSTEM, may I know how can it be done?
I understand that an image is not the best way to portrait my question, I will try to type the source in my question.
My apologies, and thank you.
You can get NodeList which contains createdby text-muted classes using document.querySelectorAll as follows.
const elems = document.querySelectorAll(".createdby .text-muted");
elems.forEach((item) => {
console.log(item.innerHTML); // This will contain the text value of the selected selector
});

Angular - Two Way Binding

I am a beginner at Angular and I covering two way binding but for some reason I do not understand what I am doing wrong with the below any input would be appreciated.
I am simply trying to understand the concept so the below code is rather simple. Per my understanding
Adding the two way binding [()] to <app-child-comp> I pass the parent field "name" from the parent component to the parent view and using property binding it provides an initialization value ( default value ) to the child component that receives the value in the #Input field.
Once the field "#Input childName " has its value using normal interpolation I can use the value how ever I please in the child template.
Now by defining an EventEmitter and then using its .emit method I should be able to pass any changes on the variable back up to the parent component and update the DOM property to reflect the changes.
Problem:
Now this is my problem the parent --> child direction the bindings are working as intended,
the name "Fin" is appearing as I expect in the input of the parent Template and in the interpolation in the child template but when I want to alter the name in the child template and have it bubble back up to the parent property it fails to update although it updates the interpolation in the child template.
Ive been trying to figure this out now for a while and everything im researching I feel says im doing it correctly but if you could please explain what im doing wrong I would much appreciate it.
Im adding this so that anyone looking in the future can learn from my mistake.
There are two ways to perform event binding given a child component
The first way is by explicitly declaring the property and event bindings as follows <app-child-comp [childName]="name" (childNameChange)="name =$event"></app-child-comp>
The second way is to use the "Banana Box" Method where the child tag transforms into <app-child-comp [(childName)]="name"></app-child-comp>
I was trying to use the second method and something that wasn't immediately clear is that there is a naming convention when it comes to the field names in the child component that needs to be followed in order for the "Banana Method" to work
Rule: If your #Input field is named "x" then your #Output EventEmitter needs to be named "xChange" the "Change" is required as the second part of the name .
Syntax: inputName + Change
So in order to resolve my problem I needed to change the naming convention from
#Input() childName:string;
#Output() changedName = new EventEmitter<string>();
to
#Input() childName:string;
#Output() childNameChange = new EventEmitter<string>();
You have to add the output in your root component:
<app-child-app [(childName)]="name" (changedName)="name = $event"></app-child-app>

Numeric variable in json style

I'm stuck in my style settings as I don't know how to put a numeric variable for the "icon-rotate" attribute.
I've tried
"icon-rotate": "{{c}}"
"icon-rotate": "{c}"
"icon-rotate": "${c}"
"icon-rotate": {c}
But nothing works I always got the error
layers[10].layout.icon-rotate: number expected, string found
See https://www.mapbox.com/mapbox-gl-style-spec/. Currently properties like icon-image & text-field support tokens.
But - implementing tokens across all properties is actively being discussed in this issue: https://github.com/mapbox/mapbox-gl-style-spec/issues/249