Find element with XPath - xpath

I have the following markup:
<div>
<div>Question1</div>
<div>
<button type="button">No</button>
<button type="button">Yes</button>
</div>
</div>
<div>
<div>Question2</div>
<div>
<button type="button">No</button>
<button type="button">Yes</button>
</div>
</div>
The following XPath expression locates two yes buttons:
//div/div/button[text()='Yes']
However I only want the Yes button of the first div as in:
//div/div[text()='Question1']
How can I locate that?

Use:
//div[div[. = 'Question1']]
/div/button[#type = 'button'][. = 'Yes']
This selects any button whose string value is "Yes" and whose type attribute has string value "button" and (the button element) is child of a div that is a child of a div that has a div child with string value "Question1" .

Your can target the first button like this (if you don't want to hardcode Question1 into your query):
(//div/div/button[text() = 'Yes'])[1]
See also MSDN XPath Examples.

Tested and working for me with your snippet:
//div/div[preceding-sibling::*[position() = 1][.="Question1"]]/button[.="Yes"]

Try //div/div[text()='Question1']/button[text()='Yes']

Try something like this
/x:html/x:body/x:div[1]/x:div[2]/x:button[2]

This should do the trick:
//div[div[text()='Question1']]/div/button[text()='Yes']
OR
//div[div/text()='Question1']/div/button[text()='Yes']
This selects the button having text='Yes' and having a parent that has a child div with text='Question1'
Also if you are interested in the first div no matter the text, use:
//div[1]/div/button[text()='Yes']
and to be more specific you should specify the parent:
/div[1]/div/button[text()='Yes'] - if it's root (as in your example)
//parentNode/div[1]/div/button[text()='Yes'] - if it's parentNode

Related

How do we crawl and fetch the data from multiple div tags having same class name? [duplicate]

I have to fetch two labels 'Text 1', 'Text 2' which belongs to same class ='xyz', which are located in two div's.Structure as shown below.
<div class='xyz'>TEXT 1</div>
<div class='xyz'>TEXT 2</div>
Can anyone please help me to solve this ?
You find elements by className and then use getText() to get the text:
List<WebElement> elements = driver.findElements(By.className("xyz"));
for(WebElement element:elements) {
System.out.println(element.getText());
}
Use FindElements method and then access to necessary div using index, e.g:
var elements = driver.FindElements(By.CssSelector((".xyz"));
//get text in first element;
elements[0].getText();
//in second
elements[1].getText(); //etc

Grails: how to pass a array (and not a string!) using remoteFunction (ajax) from controller to view?

I need to load different data in a div when I change a Select option, not only a simple string but I list/array/map of strings. My code:
View:
<div id="contextMenu">
<div id="testeDiv">${result}</div>
<form class="selecionarConta" name="formulario">
<g:select id="selecionaConta"
name="selecionarConta"
class="selectConta"
from="${menuDropDown}"
optionValue="string"
optionKey="value"
onchange="${remoteFunction(controller:'dashboard',action:'teste', update:'testeDiv', params:'\'varteste=\'+this.value')}"/>
</form>
</div>
Controller:
def teste() {
def result = [["Lemon":"${params.varteste}"],["Orange":"5"],["Grapefruit":"10"]]
[result:result]
}
Let's suppose I want to load an array or even an object in this div "testeDiv" and then any content I want, e.g. a list, or even a single element from this list e.g. <div id=testeDiv>${result[1]}</div>

MVC3: Geting values of cloned objects

I have a drop down list with options from a model; and I want to add a similar drop down list when the user clicks on a button. My drop down list and button are defined as
<div id="parent">
<div class="id">
#Html.DropDownListFor(m =>m.mymodel)
</div>
</div>
<input type="button" value="submit" onclick="JSFunc()"/>
And the function, JSFunc() is
var control = document.getElementById('id').cloneNode( true );
document.getElementById( 'parent' ).appendChild( new );
How can I get the value of the clone objects from the controller?
You must set the name attribute of a newly-created <select> to something unique that matches a parameter name in your controller.
(or parameter property name, or anything else depending on the model binder and your situation)

Validation of dynamic created form (AngularJS)

I try to made nested form with validation. All works fine, but when I remove one of nested form, validation continue to use removed form. I made jsfiddle example http://jsfiddle.net/sokolov_stas/VAyXu/
When example runs, form are valid. If click "+" button, nested form will be added and valid will be false. Then click "-" button, and valid will be false all the same.
The question is: How to remove dynamic created form from validation processing.
Well, for one thing, a <form> inside of a <form> is not valid HTML.
Second, you're not supposed to be doing DOM manipulation from inside the controller. The controller is for "business" logic. See the section on controllers here
For what you're doing, you'd probably be better off using one form, with an ng-repeat inside of it, and adding additional elements to an array:
<form name="myForm" ng-controller="FormCtrl" ng-submit="doSomething()">
<div ng-repeat="item in items">
<input ng-model="item" type="text" required/>
</div>
<a ng-click="addItem()">+</a>
<a ng-click="removeItem()">-</a>
<button type="submit">Submit</button>
<div>Form valid: {{myForm.$valid}}</div>
</form>
and the controller:
function FormCtrl($scope) {
$scope.items = [];
$scope.addItem = function() {
$scope.items.push(null);
};
$scope.removeItem = function() {
$scope.items.pop();
};
$scope.doSomething = function () {
//your submission stuff goes here.
};
}

How to rerender part of page after ajax submit of form in Lift (Scala)

this is probably a stupid question but I cannot figure out how to do it.
So I'm new to Scala/Lift and I read the ajax form chapter in http://simply.liftweb.net/index-4.8.html#toc-Section-4.8 but the "RedirectTo" in the example does not seem to be very "ajaxian" to me. Often in case of submitting a form via ajax, you would just partially rerender the same page, right?
So that's what I'm trying to do and am completely failing right now.
How do I let Lift rerender just a part of the same page after I submit the form via ajax?
Any hints would be appreciated. Thanks.
Basically, what I have looks like this:
<div id="main" class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<div class="lift:Test">
<div>
<form class="lift:form.ajax">
<fieldset>
<label for="name">Name:</label>
<input id="name" name="name" type=text>
<p></p>
<input id="save" type="submit" value="Save">
</fieldset>
</form>
</div>
<div>
<span id="theName">Name</span>
</div>
</div>
</div>
class Test {
def render = {
var name = ""
def process(): JsCmd = {
Thread.sleep(500)
S.notice("Entered name is: %s".format(name))
Noop
}
"#theName " #> "This shall be updated with the name given in the form above" &
"#name" #> (SHtml.text(name, name = _) ++ SHtml.hidden(process))
}
}
How would I update "theName" when submitting the form?
Have a look at http://lift.la/shtmlidmemoize-simple-ajax-updating (Example Code). There is SHtml.memoize and SHtml.idMemoize which automatically caches the HTML code. Not sure why it is not used in this example in the Simply Lift book.
You have a 2 step form right? The above poster is correct.
Save your transformation in a RequestVar.
in your above example, the method you want to save is render, so 1st memoize the transform:
private def renderTest= SHtml.memoize { render }
Then, you can save this memoized transformation in a RequestVar (lasts for 1 request), or maybe a TransientRequestVar depending on your needs.
private object testTemplate extends RequestVar(renderTest)
When you want to replay the transform, from an ajax event - testTemplate.is.applyAgain.
I might have misunderstood the original question, b/c if you want to do a 2 step form, you don't really need the memoize. The memoize is if something changes on your current form, and you want to update it via an ajax event, i.e. on click or on change, b/c normally the form wouldn't update unless you did an ajax submit.

Resources