I am wondering if there is a way that I can get the current element that is triggering the onBeforeChangeEvent function in jsViews. I want to get the current element that it is working on, to do some extra jQuery work on it.
A basic example is below:
$.views.helpers({
onAfterChange: function (ev)
{
//want to get element instance right here as an example.....
if (!PageSettings.cancelUpsert && ev.type == "change")
{
//do somthing to element that is currently being processed.
}
}
});
I searched through the objects being returned, but could find a stable way to get to the element. Any ideas, or tips towards where to look would greatly be appreciated. Thanks!
If you are looking for a data-linked element, such as an input: <input data-link="..." />, whose change event triggered the change, you can get that from either this.linkCtx.elem or ev.target.
More generally, the this pointer is the view object that is being changed.
There are a number of helper methods on the view object that you can use to access different elements within that view. For example this.contents("someSelector") will return a jQuery object that selects top-level elements in that view, and this.contents(true, "someSelector") will apply the selector to filter on all elements in the view (deep search not just top-level).
(You can use the selector "*" to get all elements)
Related
I have some long lists of buttons. For example, i have one single list of car models that all have the same custom data attribute of "modellist", while they have also another data attribute which is the name of that car model (Note that these buttons are NOT links).
the attached image
Now, without the need of creating a single tag for each and every one of these buttons, i need to find a faster way for this case using the google tag manager and GA4 (google analytics 4), so that i would be able to track clicks on these buttons. Does anyone know how can i do this?
I very highly appreciate your help & support here.
Here are the steps and how to do it.
1. Create a Custom JavaScript Variable;
Here is the Screenshot
The code is:
function(){
// Get the click element;
var clickElement = {{Click Element}};
// Check there is a closet parent element you want. If it doesn't then return false;
if(!clickElement.closest("div.stepped-selection__list-item"))
return false;
// Check the parent dom has the attribute you want.
// If it does, return the attribute value. Otherwise, return false;
var modelListDom = clickElement.closest("div.stepped-selection__list-item");
if(modelListDom.hasAttribute("data-trackervalue")){
return modelListDom.getAttribute("data-trackervalue");
}
return false;
}
2. Create the trigger
Here is the screenshot:
First, using the click element > match css selector > To catch all the element inside the selector. You can modify it a bit to make it more suitable in your real case.
Second, the Variable we create in step1. It will return false if something not we expected. So we don't want to trigger the tag if the Variable is return false.
3. Create the Tag.
The Tag config is the easiest one.
Just use the Trigger in step2.
And give the event name and event parameter you would like.
Give the event parameter value as the Variable in Step1.
I am trying to get the active item from this menu list to display in a different style. When I reload the page, the style gets applied for a split second, then disappears and all items share the exact same style.
There is a similar thread saying the solution is to actually have the item available as a data property in that component. I have tried that too, and it would not work. It makes more sense to have all the data from a computed property since I am using Vuex for data storing.
The template:
<li class="topic"
v-for="topic in topics"
:key="topic"
#click="selectTopic($event, topic)"
:class="{'active': topic === current}"
>
{{topic}}</li>
and the script:
computed: {
topics: function(){
return this.$store.state.topics
},
current: function() {
return this.$store.state.current_topic
}
},
The current_topic is updated with the selectTopic method in this component. It all works fine, except I can't get the current_topic to have a distinctive style.
Oh, on the styles I simply have .topic.active {border:yellowgreen solid 0.5em;}. If I do topic:active then the style gets applied when I click but only for the time I am clicking (also if I hold), but it does not get applied when reload not even for a split second.
Any leads? thank you :-)
Just as a conclusion / closing of this thread. The code I presented is correct. The problem had to do with a getter which was converting the current_topic into a title. This is why topic and current did not match inside the class binding. I figure it is still worth leaving the thread since it might be helpful for somebody else dealing with class binding inside a v-for.
I am trying to learn the PageFactory model. I understood the fact that when we do a initElements, the WebElements are located. Say for example, I click on a webelement and because of which there is a change in one of the other webelements in DOM. Now, obviously I would get a StaleElementReferenceException here. How would I resolve this issue?
Should I find that specific WebElement again knowing the fact that there can be a change in the WebElement's properties in the DOM? or is there an another way to handle this?
StaleElementReferenceException
StaleElementReferenceException extends WebDriverException and indicates that the previous reference of the element is now stale and the element reference is no longer present on the DOM of the page.
Common Reasons
The common reasons behind facing StaleElementReferenceException are as follows:
The element has been deleted entirely.
The element is no longer attached to the DOM.
The webpage on which the element was part of has been refreshed.
The (previous) element has been deleted by a JavaScript or AjaxCall and is replaced by a (new) element with the same ID or other attributes.
Solution : If an (old) element has been replaced with new identical one, the simple strategy would be to use findElement() or findElements to look out for the element again.
Answering your queries
When we do a initElements, the WebElements are located : When you call initElements() method, all the WebElements of that page will get initialized. For example,
LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
This line of code will initialize all the static WebElements defined within the scope of the LoginPageNew.class whenever and wherever it is invoked from your Automation Script.
I click on a webelement and because of which there is a change in one of the other webelements in DOM : This is pretty much possible.
As an example, in general invoking click() on a <input> tag wouldn't trigger any change of any of the WebElements on the HTML DOM.
Where as invoking click() on a <button> tag or <a> tag may call a JavaScript or a Ajax which inturn may delete an element or can replace the (previous) element by a (new) element with the same ID or other attributes.
Conclusion
So, if WebDriver throws a StaleElementReferenceException, that implies even though the element still exists, the reference is lost. We should discard the current reference we have and replace it by locating the WebElement once again when it gets attached to the DOM. That means you have to again reinitialize the class through initElements() method which inturn reinitializes all the WebElements defined in that page.
Solution
If a old element has been replaced with new identical one, the simple strategy would be to invoke WebDriverWait inconjunction with ExpectedConditions to look out for the element.
You can find relevant detailed discussions in:
How to add explicit wait in PageFactory in PageObjectModel?
References
Here are the references of this discussion:
Stale Element Reference Exception
Class StaleElementReferenceException
Selenium: How to tell if RemoteWebDriver.findElements(By) can throw StaleElementReferenceException at all?
This is a known problem with the PageFactory implementation.
If you are unlucky enough for the element to become stale in the instant between the element being found, and then the element being clicked upon, you will get this error. Unfortunately the PageFactory code does not try to find the element again if it has become stale and it throws an Exception.
I would classify this as a bug with PageFactory, it should auto re-find the element if it ever becomes stale (unless the #CacheLookup annotation is used).
The suggestion to recall initElements isn't going to fix anything, you only need to init the elements once because that binds a Java proxy class to the element in question. The page factory implementation is supposed to remove the possibility of StaleElementReferenceExceptions (hence why this is a bug)
Stale element exception is thrown in two cases
The element is no longer attached to the DOM.
The element has been deleted entirely.
When this happen you wrap your code in try catch block then you can loop and retry as many times as you need until it succeeds.
public void waitForElementPresent(final By by, int timeout){
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,timeout)
.ignoring(StaleElementReferenceException.class);
wait.until(new ExpectedCondition<Boolean>(){
#Override
public Boolean apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(by);
return element != null && element.isDisplayed();
}
});
}
I'm using Polymer and I am encountering a Problem. I think there is a good solution, but I still don't have the perfect understanding of polymer.
In my template I get a dom-repeat which gets me some _itemsas item. item.name returns the name of the item, it works just fine. Now I want to use this name to display it in a tooltip, so I call the function on-mouseenter="_showTooltip".
My function looks like this:
_showTooltip: function(e) {
var item = Polymer.dom(e).rootTarget;
//........here I get Information out of my item to use it in my tooltip and display it
}
How can I transfer the information of my original item to this function?
Thanks in advance!
You did not mention or tag which version of Polymer you're using so I will point you to the docs for Polymer 2 because that's what I use, but I am guessing something similar must exist for Polymer 3 also.
Any event triggered from elements rendered inside a dom-repeat will get a model key added, under which you will have the context, so you will have your item from HTML there.
You can see that in the docs here.
To start you can try to:
_showTooltip: function(e) {
var item = Polymer.dom(e).rootTarget;
//........here I get Information out of my item to use it in my tooltip and display it
console.log(e.model); debugger;
}
and continue from there..
The BluePrintJS React InputGroup component is great and convenient for modern user-interface. But unfortunately the React component do not allow access to the <input> element inside.
I need to access the input element for 2 main reasons :
if I have 50 InputGroups in my form, I don't want to write 50 OnChange() callbacks. When the user finishes all inputs, I want to get all InputGroup.value(), which is not possible (it is possible with regular input element thanks to HTMLInputElement.value, but InputGroup does not allow accessing internal input)
At form displaying, I need to focus on first field. InputGroup has no function focus(), while HTMLInputElement has one.
Briefly there are 2 functions missing in InputGroup : GetValue() and Focus() , and I cannot see why they are missing.
Any suggestion will be greatly appreciated.
Thanks a lot.
I found the way of getting the input ! with :
inputRef={(input:HTMLInputElement) => {
this.logininput=input;
}}
(didn't see it at first time).
Now I have the input object, I can set focus at "didmount", and I can get the value with logininput.value.
Thanks
Slightly different variation but this works too:
inputRef:(input:HTMLInputElement | null) => {
// your code here
return input;
}
}}
just be aware that code runs when you just render the component, depending on your usage, to me happens when I click the child control on a select.
In my case, I just wanted to modify an input that works for text search on a select.