#item
creates a div with id="item"
.box#item
creates a div with class="box" and id="item"
.box#="item "+x
creates a div with class="box" and a comment '#="item"+x'
.box#
="item"+x
throws "Illegal element: classes and ids must have values."
How do I get set the id to a variable?
There are two ways:
The long form way (define the id as if it were a regular attribute):
.box{:id => "item_#{x}"}
produces this (x is what ever x.to_s evaluates to):
<div class="box" id="item_x">
The short form way:
.box[x]
produces the following assuming x is an instance of item:
<div class="box item" id="item_45">
See the HAML reference for more information.
You can set the id and class in HAML the following ways
The normal way
.box.item#item
<div id="item" class="box item"></div>
If you need to interpolation you can use this format
.box{id: "item_#{123}", class: "item_#{123}"}
<div id="item_123" class="box item_123"></div>
This format generates the class and id using the object reference
# app/controllers/items_controller.rb
#item = Item.find(123)
.box[#item]
<div id="item_123" class="box item"></div>
If you need to prefix something
.box[#item, :custom]
<div id="custom_item_123" class="box custom_item"></div>
If you need a custom class and id generation you need to add the following method to model.
class CrazyUser < ActiveRecord::Base
def haml_object_ref
"customized_item"
end
end
And then you will get the customized class
.box[#item]
<div id="customized_item_123" class="box customized_item"></div>
Refer:
http://haml.info/docs/yardoc/file.REFERENCE.html#object-reference-
http://haml.info/docs/yardoc/file.REFERENCE.html
Related
There is the structure like:
<div class="parent">
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">
<div class="CheckBox">
</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
</div>
In my script I am writing a loop for each of the 4 div's under div[#class='parent'] and aiming to click the checkbox if there is, i.e.
members = page.all(:xpath, '//div[#class='parent'])
members.each do |a|
if **page.has_xpath?(a).find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']")**
a.find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
However I can't look for the correct usage of has_xpath? with xpath including variable.
Please advice? Thank you!
has_xpath? takes an XPath expression (not an element) and returns a boolean (true/false) based on whether there are any elements that match that expression within the current scope - http://www.rubydoc.info/gems/capybara/Capybara/Node/Matchers#has_xpath%3F-instance_method. Since it returns true/false you can't then call find on it. For the example you posted there's no need for XPath or checking for the existence of the elements, just find all the matching elements and call click on them. Something like
page.all('div.parent div.fieldRow div.Checkbox').each { |cb| cb.click }
or
page.all('div.parent div.Checkbox').each { |cb| cb.click }
if the fieldRow class isn't something you really need to check.
Note: this assumes clicking the elements doesn't invalidate any of the other matched elements/change the page.
If you REALLY need to do it with the whole members and looping on them , using XPath, and checking for presence then it would be something like
members = page.all(:xpath, './/div[#class='parent'])
members.each do |a|
if a.has_xpath?(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']")
a.find(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
Note: the .// at the beginning of the XPath expressions is needed for scoping to work correctly - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap - which is an issue using CSS selectors doesn't have, so you should really prefer CSS selectors whenever possible.
I have two field-set on my page. None of them have any id or class.
Now i want to fill specific field in second field-set.
Currently i a doing something like this which is not working:
within_fieldset('fieldset') do
fill_in 'app_answers_attributes_0_answer', with: 'My First Answer'
end
click_on 'Submit'
And it is giving error:
Capybara::ElementNotFound: Unable to find fieldset "fieldset"
Any idea on how to do that?
within_fieldset takes the id or legend text of the fieldset - http://www.rubydoc.info/gems/capybara/Capybara/Session#within_fieldset-instance_method - so it's not really surprising within_fieldset('fieldset') isn't working for you. How you can do what you want really depends on how you're HTML is structured. For instance if you're fieldsets have legends
<fieldset>
<legend>Something</legened>
...
</fieldset>
<fieldset>
<legend>Other thing</legened>
...
</fieldset>
You can do
within_fieldset('Other thing') do
...
end
If you don't have legends, but have wrapping elements
<div id="first_section">
...
<fieldset>...</fieldset>
<div>
<div id="second_section">
<fieldset>...</fieldset>
</div>
then you can just scope using CSS to the correct fieldset
within('#second_section fieldset') do
...
end
If instead the fieldsets are siblings
<div>
<fieldset>...</fieldset>
<fieldset>...</fieldset>
</div>
then you can just scope to the second fieldset with a CSS sibling selector
within("fieldset + fieldset") do
...
end
I want to create taglibs to simplify a webpage that represents a user dashboard. There are 2 taglibs I want to create. The first is a generic panel that will be used elsewhere, the second is a more specific version of the panel.
The GSP is called from a controller with the following model:
def index() {
def timelineItems = [
[details: "Some text"],
[details: "Some other text"]
]
render(view: "index", model: [timelineItems: timelineItems])
}
My desired GSP looks like this:
<dash:panel panelClass="col-lg-8" panelTitle="Service History">
<p>Some text in the body here</p>
<dash:timelinePanel timelineItems="$timelineItems" />
</dash:panel>
I want to put my HTML code in templates to make editing it simpler, so I call render from inside the tag lib and pass a data model. The taglibs look like this (within a namespace called dash):
def panel = {attrs, body ->
out << render(template: "/dashboard/dashboardPanel", model:[panelClass: attrs.getAt("panelClass"), panelTitle: attrs.getAt("panelTitle"), body: body()])
}
def timelinePanel = { attrs ->
out << render(template: "/dashboard/dashboardTimelinePanel", model: [timelineItems: attrs.getAt("timelineItems")])
}
This is my generic panel template: it should render the data in the top divs and then simply render the body passed to it in the model:
<div class="${panelClass}">
<div class="panel panel-default">
<div class="panel-heading">
${panelTitle}
</div>
<div class="panel-body">
${body}
</div>
</div>
</div>
This is my timeline template: it should render the details of each of the timeline variables passed in the model by the controller.
<g:each in="${timelineItems}">
<p>${it.details}</p>
</g:each>
I'm expecting to see a div which includes something like:
Some text in the body here
<p>Some text</p>
<p>Some other text</p>
However, I get the following error:
Error evaluating expression [it.details] : No such property: details for class: java.lang.String
My map appears to be being converted to a string and I can't access the map. What am I doing wrong please? I want to define multiple tags which can be used inside one another. How do I do this?
I have the following div...
<div class="list_entries" id="<%= entry.id %>">
How might I give the div id a name as well as using the entry.id?
Example for later use in JavaScript...
$('#<%= entry.id %>').css("text-decoration", "line-through");
This is so I can have a strike through on just one specific entry instead of all of the entries.
DOM IDs must be unique across the entire document. Unless you're using that same entry.id elsewhere for OTHER dom elements, there's no need for prefixes.
That being said, it could be as simple as:
<div id="foo<%= entry.id %>">
^^^
$('foo<%= entry.id %>').etc....
^^^
I'm using Grails 2.2.3 and Fields plugin 1.3.
I want to customize fields to manage one-to-many relationships using select tag.
In views/_fields/oneToMany/_input.gsp I have:
<g:select name="${property}.id" from="${type.list()}" optionKey="id" value="${value}" class="form-control one-to-many" noSelection="['null': "${label}"]" />
But type is a set, so I can't use list function.
How can I retrieve target domain class?
As long as you use a Map to declare the relationship, for example:
static hasMany = [ books: Book ]
You can get the list of the referenced domain, which is the key from the hasMany property of the bean, so the from attribute should change to
from="${bean.hasMany[property].list()}"
Alternatively you can pass the list to the _input.gsp template prefixing the variable name with input-, e.g.
<f:field property="books" input-domainList="${bookInstaceList}" />
In the _input.gsp template you can use the variable as follows:
from="${domainList}"
or mixing both methods:
from"${domainList ?: bean.hasMany[property].list()}"
I found this solution for the problem, this code work fine with one to many and one to one
<div class="input-group">
<g:select name="${persistentProperty.toString().contains('one-to-many')?property:property+'.id'}" value="${value?.id}" required="${required}"
noSelection="${['null':'Escriba...']}" class="select2 col-md-6"
multiple="${persistentProperty.toString().contains('one-to-many')?true:false}" from="${grailsApplication.getDomainClass(persistentProperty.properties['associatedEntity'].toString()).clazz.list()}"
optionKey="id"></g:select>
</div>
This solution can be helpful. I found in the documentacion of Fields Plugin, the persistentProperty is a class type DomainProperty but their methods doesn't works and I found the correct class is org.grails.datastore.mapping.model.MappingFactory
you can use .toArray() method on your Set instead of .list().
ale
You can use the code below to identify the Element of your collection
def className = bean.hasMany[property].properties.typeName
See my "views/_fields/oneToMany/_input.gsp" implementation:
<%# page defaultCodec="html" %>
<%
def className = bean.hasMany[property].properties.typeName
def simpleName = Class.forName(className).simpleName
def beanSimpleName = bean.class.simpleName
def createUri = "/${simpleName.toLowerCase()}/create?${beanSimpleName.toLowerCase()}.id=${bean.id}"
%>
<a id="add${simpleName}" name="add${simpleName}" href="${createLink(uri: "${createUri}")}">
Add ${simpleName}
</a>
<ul>
<g:each var="item" in="${value}">
<li>
${item}
</li>
</g:each>
</ul>