Reputation: 177
I am trying to return an element from a list of elements and then perform some other actions like click, drag and drop etc. I tried following code but getting error saying nodes.click() not a function
var nodes = vectorpo.yfilesCanvasMain.all(
by.css("g text[fill-opacity='1']")
)
.each(function (eachnode, index) {
eachnode.getText().then(function (text) {
if (text == 'hello world') {
return eachnode;
}
})
});
nodes.click();
Upvotes: 0
Views: 895
Reputation: 211
Rather than returning eachnode
, we can append eachnode to an ElementFinder[]
array and return that. Then we will need to loop through the array to click each one.
// Make a reusable function
async function reusableFunction() {
var nodes = []; // Change 1: Initialize local array
vectorpo.yfilesCanvasMain
.all(by.css("g text[fill-opacity='1']"))
.each(function(eachnode, index) {
eachnode
.getText()
.then(function(text) {
if (text === 'hello world') {
nodes.push(eachnode); // Change 2: add the node to an array
}
})
});
return nodes; // Change 3: return
}
var nodeArray = await reusableFunction(); // Change 4: function call
// Change 5: since we return an array of nodes,
// we need to loop through the array to click each one
nodeArray.forEach(function(node) {
node.click();
});
Upvotes: 0
Reputation: 177
After reviewed few other options I tried the following method. I am trying to find the index value of the selected element and want to return that value to my call function. But when I try to output the returned value I am getting null
function getNodeIndex () {
var nodeIndex
var nodes = vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']"));
return nodes.each(function (eachNode, index) {
// for (var i = 0; i < noOfNodes.length; i++) { //Somereason if I use for loop the i is always shows as length of the element when I try to print in below if statement
eachNode.getText().then(function (text) {
if (text == 'hello world') {
nodeIndex = index;
console.log("printing index value is " + nodeIndex);
//the nodeIndex is printing correct value
}
})
return nodeIndex;
})
And in another script I used following script
getNodeIndex().then(function(value){
console.log("printing node index after retrieving in function ", value)
})
Here the value is printing as null. Please let me know what am I missing here.
Most of your code is correct, but a wrong on return
.
A tiny change as following can fix your problem.
return nodes.each(function (eachNode, index) {
eachNode.getText().then(function (text) {
if (text == 'hello world') {
nodeIndex = index;
console.log("printing index value is " + nodeIndex);
}
});
})
.then(function(){
return nodeIndex;
})
Upvotes: 0
Reputation: 621
As per your problem statement, You are interested in filtering out the array of elements and want to perform some action on filtered list of elements. As i stated problem and understood correctly then function 'each' is not suitable for this because 'each' function meant for iterating each element of ElementArrayFinder object hence Promise is returned and resolved after calling each elementFinder. 'each' function is used to solve different typr of problems.
So, what is the right approach to address problem you mentioned?
ElementArrayFinder class also provide function 'filter'. This function is meant for filtering out this list of elements. Therefore 'filter' function doesn't return any promise, it returns object of ElementArrayFinder after applying filter condition defined inside it. Refer following code snippet applied for the code you share.
vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']")).filter(eachNode, index){
return eachNode.getText().then(function(text){
return text === 'hello world';
});
}).first().click();
Code before first().click() will again return object of ElementArrayFinder which satisfy the condition of element with 'hello world' text. That's why we used first() to get the first element from ElementArrayFinder object.
ElementArrayFinder.each()
only can return null, if you stick to use each()
to archive your goal, you can do as following:
var found, node;
vectorpo.yfilesCanvasMain.all(
by.css("g text[fill-opacity='1']")
)
.each(function (eachnode, index) {
// if had found the wanted node, end this loop in advance
if (found) return;
eachnode.getText().then(function (text) {
if (text == 'hello world') {
node = eachnode; // assign wanted node to outside variable `node`
found = true; // change flag: found to true
}
})
})
.then(function() {
// the function inside this `then()` will only be executed when above `each()` complete
// if the ouside variable is not null or undefined,
// means find wanted node, then click
if (node) node.click();
});
Even you can archive same goal through each()
, but it's more complex than filter()
, I'd recommend to use filter()
Upvotes: 1
Reputation: 16
Write return nodeIndex just after closing the if statement
function getNodeIndex () { var nodeIndex var nodes = vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']")); return nodes.each(function (eachNode, index) { // for (var i = 0; i < noOfNodes.length; i++) { //Somereason if I use for loop the i is always shows as length of the element when I try to print in below if statement eachNode.getText().then(function (text) { if (text == 'hello world') { nodeIndex = index; console.log("printing index value is " + nodeIndex); //the nodeIndex is printing correct value } return nodeIndex; }); })
PS : I am using my mobile browser to type this answer so the indentation might not look ok.
Upvotes: 0