select checkbox with hidden input type - ruby-on-rails

Folks,
I am using watir-webdriver, I have a piece in my HTML DOM which gets generated on the fly when I enter some credentials, this piece has a bunch of checkboxes, the number of checkboxes vary, I have to select one checkbox, below is an example of this, here I want to select the second checkbox(the one that has value "BS" for the input type hidden but the value for input type checkbox is same for all):
<li class="dir">
<input type="checkbox" value="1" onclick="$(this).next('.should_destroy').value = (this.checked?0:1)" name="should_not_destroy">
<input class="should_destroy" type="hidden" value="1" name="import[dir_attributes][][should_destroy]">
<input type="hidden" value="" name="import[dir_attributes][][id]">
<input type="hidden" value="Automation" name="import[dir_attributes][][path]">
<span class="dir_mode">Include</span>
Automation
</li>
<li class="dir">
<input type="checkbox" value="1" onclick="$(this).next('.should_destroy').value = (this.checked?0:1)" name="should_not_destroy">
<input class="should_destroy" type="hidden" value="1" name="import[dir_attributes][][should_destroy]">
<input type="hidden" value="" name="import[dir_attributes][][id]">
<input type="hidden" value="BS" name="import[dir_attributes][][path]">
<span class="dir_mode">Include</span>
BS
</li>
I may be able to do this with XPATH, but wanted to try a non XPATH solution. The input type hidden has the appropriate value that I need, for example above the second checkbox has value "BS" for input type hidden. I tried to use the hidden method like this:
h = ##browser.hidden(:value, "BS")
h.select
But I dont know what to do after this. I am trying to select the checkbox based on the value of the hidden element. Any feedback is much appreciated.

I would suggest using the visible elements instead. I think it makes it easier to read the test and seems more stable.
Try:
##browser.li(:class => 'dir', :text => /BS/).checkbox.set

Here we go, I think this will do it
Since you have to select the checkbox based on the hidden, you're going to have to go up a level to the containing li, then drill down to the checkbox
#browser.hidden(value: 'BS').parent.checkboxes.first.set

Related

Is there a way to populate user input fields with default values in thymeleaf spring?

Is there a way to populate user input fields with default value in thymeleaf?
I understand that th:field replaces the value="" tag, but I need to populate the user inputs with default number so, that if the user does not provide input, number 0 will be passed as the input.
I cannot do this in controller as my input type needs to be number, and my model attribute is String[] arraylist.
<input type="number" id = "a2s" name="a2" class="newMatch" value="0" min="0" max="11" th:field="*{player1score}">
<input type="number" id = "b2s" name="b2" class="newMatch" value="0" min="0" max="11" th:field="*{player2score}" >
Try this way:
<input th:value="*{player1score != '' ? player1score : 0}" //...other attr />
th:field will override value, name and id attributes. To populate the field you will have to use the tags separately, like so:
<input type="number" id = "a2s" name="a2" class="newMatch" value="0" min="0" max="11" th:name="*{player1score}" th:id="*${playerscore}">
Solved this by using name and id html fields to replace the need for th:field="*{myVar}" . Like so:
<input type="number" class="newMatch" value="0" min="0" max="25" name="player1score" id="player1score" >
<input type="number" class="newMatch" value="0" min="0" max="25" name="player2score" id="player2score" >
The th:field tag replaces name , id and value fields. So one way to do this is to just use html tags instead.

Permit any parameter nested inside a given param

I have a list of parameters like this:
<input class="form-control" name="analysis[strengths][0]" id="swot_analysis_strengths_0" type="text">
<input class="form-control" name="analysis[strengths][1]" id="swot_analysis_strengths_1" type="text">
...
etc
Then there's also
<input class="form-control" name="analysis[weaknesses][x]" id="swot_analysis_strengths_2" type="text">
<input class="form-control" name="analysis[opportunities][x]" id="swot_analysis_strengths_2" type="text">
<input class="form-control" name="analysis[threats][x]" id="swot_analysis_strengths_2" type="text">
In my controller I have
params.require(:swot_analysis).permit(:strengths, :weaknesses, :opportunities, :threats)
That doesn't work. The only way I've got it to work so fat is by doing this
sanitized_params = params.require(:swot_analysis).permit(:strengths =>['0','1'], :weaknesses =>['0','1'], :opportunities =>['0','1'], :threats =>['0','1'])
However the number of members for each array will vary, users will be able to add and remove members as they please. So I need a method to simply permit any sub-param of the original for parameters.
Would be nice to allow it only if it's a number, but not really a priority right now
This should take care of the member array lengths:
params.require(:swot_analysis).permit(:strengths =>[], :weaknesses =>[], :opportunities =>[], :threats =>[])
http://api.rubyonrails.org/classes/ActionController/Parameters.html

Passing Connectionstring as parameter in SSRS through URL

I am working on an application using Classic ASP and SQL Server 2008 R2. We are using SSRS for the reports. Now the datasource changes depending on the user. I have been using a parameter for the connectionstring. It is working fine but the problem is the connectionstring shows in the URL. Is there a way to hide it? Or is there a better way.
Please Help.
Yes - change the method on your form to POST and use the Request.Form syntax instead of Request.QueryString:
<form id="myForm" method="post" action="myPage.asp">
<label for="txtBox">Type something</label>
<input type="text" id="txtBox" name="txtBox" />
</form>
<%
Dim value
value = Cstr(Request.Form("txtBox"))
If value <> "" then
'Do your processing
End if
%>
-- EDIT --
To be honest, though, I would not store my connection string on my form like this. You'd be far better off storing it in an Application level variable, like so:
Application("CON_STRING") = "...blahblahblah..."
This should be stored in the Application_OnStart event of the Global.asa* file.
*
Apologies for the link to w3schools - it was the best at the time!
-- EDIT 2 --
Try using an iframe to display the info...
<form id="frmRender" action="ABCD/ReportServer?/Reports/rptSalesReport.rpt"; method="post" target="_blank">
<input type="hidden" name="rs:Command" value="Render">
<input type="hidden" name="rc:LinkTarget" value="_blank">
<input type="hidden" name="rs:Format" value="HTML4.0">
<input type="hidden" name="rc:Parameters" value="False">
<input type="hidden" name="ConnectionString" value="<%=Session("ConnectionString")%>">
<input type="hidden" name="StartDate" value="<%=StartDate%>">
<input type="hidden" name="EndDate" value="<%=EndDate%>">
<a id="linkInfo" href="javascript:generateSsrs();">Generate Report</a>
<iframe id="ssrsReport" class="reportHeightWidth"></iframe>
</form >
<script language="javascript">
function genreateSsrs() {
document.getElementById("ssrsReport").src = "ABCD/ReportServer?/Reports/rptSalesReport.rpt?rs:Command=Render&rc:LinkTarget=top&rs:Format=HTML4.0&rc:Parameters=False&ConnectionString=<%=Server.URLEncode(Session("ConnectionString"))%>&StartDate=<%=StartDate%>&EndDate=<%=EndDate%>";
}
</script>
That's a rough version, but it's untested, so may need some tweaks.
In you code, use the below code
="Data Source="+Parameters!DatabaseServerName.Value+";Initial Catalog="&Parameters!DatabaseCatalogName.Value

MVC EditorFor and ID generator

I have a ViewModel with rows repeated by using a EditorTemplate
#Html.EditorFor(x => x.Rows)
The HTML generated looks like this (only 1 field in this sample)
<input id="Rows_0__Comment" name="Rows[0].Comment" type="text" value="a" />
<input id="Rows_1__Comment" name="Rows[1].Comment" type="text" value="b" />
<input id="Rows_2__Comment" name="Rows[2].Comment" type="text" value="c" />
This is all fine. But I have a server round trip where some logic removes X rows.
model.Rows = model.Rows.Where(x => x.WhatEver()).ToList();
Now the index based ID strategy used in the HTML render doesn't align with what is posted. So values can be posted to the wrong row.
Can I customize the ID generator to use a ID from my model?

Is it good or bad practice to rely on name attribute in the form to post the model to MVC controller?

I have a model containing some complex types including nested lists. So I cannot simply use the model.
My initial thought is using knockoutjs to take care of the user interactions (add/delete list items etc.), and post knockoutjs view model via ajax.
But after some googling, I found I could give meaningful name attributes in my form elements and do regular form submit to post my form model like this.
<input checked="checked" data-val="true" data-val-required="The Boolean field is required." name="Questions[0].SubQuestions[0].OptionAnswers[0]" type="checkbox" value="true">
Of course I still need some javascript for list manipulations and stuff.
Which approach is more preferred?
EDIT:
Sorry for the indexing issue. I was aware it should be sequential and start from 0. I just took a random element from my generated html. The indexing is not really my issue. I just would like to know which approach is more preferred.
I start liking the regular form submission way as it takes advantage of the validation feature of DataAnnotations and Html.ValidationSummary. What's the advantages for ajax post?
You are very close to understand the concept how asp.net mvc model binder works out of the box.
This is the link to an article from where I learnt how to achieve similar requirement.
The way that mvc model binder reads in the properties is by looking for parameterName[index].PropertyName. The index must be zero-based and unbroken. Say suppose, if you have your html like below which is a list for example and it can be your Questions list which is a complex type:
<input type="text" name="people[0].FirstName" value="George" />
<input type="text" name="people[0].LastName" value="Washington" />
<input type="text" name="people[1].FirstName" value="Abraham" />
<input type="text" name="people[1].LastName" value="Lincoln" />
<input type="text" name="people[3].FirstName" value="Thomas" />
<input type="text" name="people[3].LastName" value="Jefferson" />
When you submit the above values to asp.net mvc controller, the above value turns into:
people%5B0%5D.FirstName=George&people%5B0%5D.LastName=Washington&people%5B1%5D.FirstName=Abraham&people%5B1%5D.LastName=Lincoln&people%5B3%5D.FirstName=Thomas&people%5B3%5D.LastName=Jefferson
The mvc model binder then read the above data as:
people[0].FirstName = "George"
people[0].LastName = "Washington"
people[1].FirstName = "Abraham"
people[1].LastName = "Lincoln"
people[3].FirstName = "Thomas"
people[3].LastName = "Jefferson"
So, as you can see we have list items for index 0, 1 and then 3. It is broken! This results in mvc model binder only translating this data to a list of type people for only two items i.e. index 0 and 1. It excludes 3 as there was no data at index 2.
this answer has information from the same article. If you understand this, you will understand the role of name attributes and you will appreciate how easy it is to follow the rules and mvc binder will understand all your posted data.
If you want to make sure that mvc binder constructs a list from the posted data even if any index is missing then refer Eric's answer
Yoda's answer is very very good. However there is a known way to have a list of Non-Sequential Indices for postback as Phil Haacked describes in Model Binding To A List (Non-Sequential Indices heading)
<input type="hidden" name="products.Index" value="0" />
<input type="text" name="products[0].Name" value="Beer" />
<input type="text" name="products[0].Price" value="7.32" />
<input type="hidden" name="products.Index" value="1" />
<input type="text" name="products[1].Name" value="Chips" />
<input type="text" name="products[1].Price" value="2.23" />
<input type="hidden" name="products.Index" value="3" />
<input type="text" name="products[3].Name" value="Salsa" />
<input type="text" name="products[3].Price" value="1.23" />

Resources