Not in the tutorial, but in the github repo, there is the following line:
console.log("tab change: " + e.target.getAttribute('name') +" selected = " + e.detail.isSelected);
And e.target.getAttribute('name') is always producing null.
Q: Why?
e.target referes to the <paper-tabs> element, which indeed has no attribute name. The target is the element that sent the event.
The selected/deselected <paper-tab> element can be found in e.detail.item, so console.log(e.detail.item.getAttribute("name")) prints the correct name attribute.
(If one uses declarative event mapping, the event detail data is passed in the event handler as a shortcut in a second parameter.)
Related
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.
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>
I found that in Chrome DevTools it is suggested to use $x for XPath expressions lookups. But what if one already gets the desired DOM element and wants to continue searching, or may be wants to get some parents attributes.
Is there a way to use $x search starting from the given DOM element (treating this element as a DOM root)?
Try
$x
in the Google Chrome console and it outputs
ƒ $x(xpath, [startNode]) { [Command Line API] }
so that suggests there is an optional second argument to be treated as the context node or start node.
For instance on this page when I use
var codeElements = $x('//*[. = "$x"]');
I get
(5) [code, code, pre.lang-xml.prettyprint.prettyprinted, code, span.pln]
in the console for codeElements and when I use
var parentElements = codeElements.map(el => $x('..', el)[0]);
to compute the parent node of each item in the codeElements array I get
(5) [p, p, div#wmd-preview.wmd-preview, pre.lang-xml.prettyprint.prettyprinted, code]
for parentElements.
So you can pass in the context node as the second argument to $x.
Yes, $x accepts a second argument named startNode which, as its name suggests, is exactly what you are looking for.
You can use it like this:
var myNode = document.getElementById('myId'); // obtain any node in any manner you need to
var childElements = $x('*', myNode);
console.log(childElements.length);
Yes, but you need to use an xpath expression to start from one specific tag, then jump to another tag or get attributes,
Example
//span[#id='test23']//..//a[#id='233']
Also using keywords like "ancestor", "following", "following-sibling"etc.
I suggest you lookup more on Xpath on the net
I am getting the following error:
The expression you entered has an invalid reference to the parent property
On the following IF condition, the issue occurs on focus of a Textbox
If Me.AB.Value <> "" And Me.Parent.Respondent = "County of ABC" And (Me.AB.Value <> GenAB) Then
End If
A control (in this case, the textbox) has the form as it's parent, so you can reference properties of the parent (the form) when you're looking at the parent relative to the control. However, you're referring to the control from the perspective of the form --> the "Me" object, so when you refer to "Me.Parent", your asking the code to look for the parent of the form, not the textbox.
If you're looking for a control on a parent form to a subform, then it looks like your reference to "Respondent" may be the issue. Try referring to it as "Me.Parent.Respondent.Value" instead.
Also, if "Respondent" is allowed to be NULL, the if statement comparison can also fail. In those cases, I append a zero-length string to ensure the result is STRING data:
If Me.Parent.Respondent.Value & "" = "ABC" Then
So I am making a data entry program where the user presses buttons to generate new inputs (numbers text etc.) and when finished the lists are generally between 100-10000 items.
The program has been coming along well, but now I am at a point where one set of data entered must generate the coices for an array [1,2, . . .] which is part of a later set of data.
So what I have done is setup buttons with the ID based on the earlier inputs. (The whole data set is saved as a JSON)
And what I want to do is when the button is pressed it looks pressed and writes to an HTML element the ID of the button which will later be read and saved to JSON.
My problem is centered on getting the correct information back to the user.
function doStuff(container){
for (var u = 0, c = someJSON.length; u < c; u++){
var someButton = document.createElement('button');
someButton.id = someJSON.id;
someButton.className = 'someButton';
someButton.onclick = function() {
writeIDToHTML(container,someButton,someButton.id);
}
container.appendChild(someButton);
}
}
function writeIDToHTML(container,theButton,theID){
console.log("theID")
console.dir(theID)
}
This prints only the last ID in the loop. How do I get each ID to each button?
The other thing to do is to give the button a pressed look.
Bonus points if it is reversable.
You should not add a listener on each element. The way to do it is adding a listener on the container and get the id of the clicked event (via event.target). This is called event delegation.
I could explain it, but this guys made a perfect answer to your question : http://davidwalsh.name/event-delegate
Btw, you should consider using a library like jquery to manipulate your DOM. It implements event delegation and advanced cross browser DOM manipulation utilities. For instance, you would not need to add a 'container' property since you can access it by the parent() method.