Grails: Load data on one ComboBox depending on another - grails

Let's say I have a combobox with the options GENERAL, AIR, GROUND, and SEA
<g:select name="group" from="${['GENERAL', 'AIR', 'GROUND', 'SEA']}" valueMessagePrefix="default.category" value="${tipoN}" />
And then another combobox that loads certain information depending whether you select GENERAL, AIR, GROUND, or SEA.
Let's say GROUND has 3 options, FedEx, USPS, DHL, but AIR has complete different ones, AIRPLANE, JET, HOT AIR BALLOON.
The name of the other <g:select> should be "commodity"
I thought about creating a javascript file and treating everything like HTML but I did some google research and is not as simple as I thought.
Does anyone know what would be the best way to do this?? Thanks in advance!
FG

Sounds like you'll want to use AJAX for this. One way you could do it is by using a combination of templates, and domain objects:
// grails-app/domain/ShippingOption.groovy
class ShippingOption = {
String method, // can be 'ground', 'sea', 'air', or 'general'
name // can be 'fedex', 'ups', etc.
def options = {
def meth = params.method ?: "general"
def comList = ShippingOption.findByMethod(meth)
render(template:"shippingList", model: [ commodityList: comList ])
}
}
And the template:
<!-- grails-app/views/_shippingList.gsp -->
<g:each var="opt" in="${commodityList}">
<option value="${opt.name}">${opt.name}</option>
</g:each>
And in your gsp with the select box on it:
<!-- ... other stuff is before here ... -->
<g:select name="method" from="${['GENERAL', 'GROUND', 'SEA', 'AIR']}"
onchange="${remoteFunction(action:'options', update:'commodity',
params:''method=' + this.value' )}" />
<select id="commodity"></select>
I'm sure I've messed up some syntax, and you'll definitely have to refactor this a bit to work with your code. But at least you've got the general idea.
And to use them, add them to the database as ShippingOptions. Here's one way to do it.
["fedex", "ups"].each { name ->
def so = new ShippingMethod(method: "ground", name: name )
so.save()
}
PS: You'd also be able to render the shipping methods dynamically, as well.
See also: remoteFunction, g:select, templates, and AJAX

I would consider re-designing your UI and changing the flow.
A drop-down dependency that you are describing suggests the form should probably be split and adopting a 'wizard-like' solution will result in a more user-friendly and solid solution that will work also without JavaScript.

I have a worked example using AngularJS and Grail here:
http://wordpress.transentia.com.au/wordpress/2013/12/24/keeping-up-with-the-joneses/
(apologies if this is not appropriate SO 'style', but I dont' think that posting 100s of lines of code and verbiage is appropriate, either).

Related

Dynamic Context Binding in XML

I have odata coming from backend. I have two select controls on my SAPUI5 page. The first select displays a list of items received from the backend. The second select changes depending on what is selected from the first select control.
Right now I am constructing in the controller a new path for "planets" select. Is it possible to change the "planets" items path depending on the "stars" selected item just in the XML? Without using Javascript?
I would like to do something like this:
<Select id="stars"
items="{
path: '/Stars'
}">
<core:Item key="{StarID}" text="{StarName}" />
</Select>
<Select id="planets"
items="{
path: '("/Stars('" + StarID + "')/toPlanets"'
}">
<core:Item text="{PlanetName}" />
</Select>
Unfortunately, I do not believe that there is any existing functionality to do something like this naively in UI5. The only thing that is similar is binding replacement during XML preprocessing, but you cannot use that for your situation.
I have met this situation a lot of times in the past and have created a helper control for dealing with this (might not be the perfect solution, but it works). It only makes sense to use a similar approach if you have this kind of construct in multiple places (so you avoid having the same boilerplate code in your JS controllers).
You can find here an example implementation of such a control and here an example usage. Basically this allows you to have a reusable mechanism for doing such an "indirect binding" without resorting to event listeners.

Find elements by data attributes

I'm improving my tests with RSpec and capybara-webkit, trying to delete all the css and xpath selectors like
find('#edit_user > div:nth-child(7) > div > div > button').click
and I'm looking for the best option to replace them.
I was going to use the css class of the elements but some "pro" capybara tester said this is not the best option.
So my question is: can I use the dataattributes in my tests?If I have an element
<button name="button" type="submit" class="button last" data-test="edit.update">Update/button>
will I be able to do
find('edit.update').click
?
And do you think it is a good idea? If you have more ideas/infos about this topic, feel free to comment!
To locate elements by their data-* attribute, you need to use a CSS-selector or XPath.
For the CSS-selector:
find('button[data-test="edit.update"]').click
For XPath:
find('//button[#data-test="edit.update"]').click
Whether or not it is a good idea really depends on the application. You want to pick something that uniquely identifies the element. If "edit.update" is not going to be unique, it would not be a good choice to use. The class attribute would be fine if the button had a unique class, which "button" and "last" are not likely to be.
The best approach is really to use static id attributes as they should be unique within the page and are less likely to change. The find method also supports locating elements by id, which means you do not have to write CSS-selectors or XPath.
The answer given by Justin Ko is correct, I just wanted to add something slightly more advanced which can help with test readability in some situations. You can add your own "selectors" to Capybara, so if you really wanted to select things by a data-test attribute (not a great idea since you don't really want to be adding attributes just for testing) a lot you could do
Capybara.add_selector(:dt) do
css { |v| "*[data-test=#{v}]" }
end
which would allow
find(:dt, 'edit.update')
this can make tests understandable while also limiting complicated css or path queries to a single place in your test code. You can then define a method such as
def find_by_dt(value)
find(:dt, value)
end
if you prefer the look of find_by_dt...) to find(:dt, ...)
You can also add filters and descriptions to your own selections for more flexibility, better error descriptions, etc - see https://github.com/jnicklas/capybara/blob/master/lib/capybara/selector.rb for the built-in selectors provided by capybara

Going from Webforms to MVC 4

So I'm converting a WebForms application into ASP.NET MVC 4 and I would like to make sure that I'm making correct coding choices and assumptions.
1). Is the MVC equivalent of a user control a partial view?
2). In an aspx page you have a control like
<asp:Label id="X" runat="server">
with the following code in the code behind:
X.Visible = some_condition ? true : false;
Ok so, for MVC is this code equivalent?
View:
<label id="X" style="display: #Model.IsViewable">
Model:
IsViewable = some_condition ? "inline-block" : "none";
1.) Well, kinda, sorta, but no not really. Very different things - a detailed explanation would be lengthy.
2.) Equivalent maybe, but not really a good thing to do. Your model should contain data only. But yes, you can use this data in your razor views to conditionally do things including show or not show things. However, putting the css strings straight into your model data is klunky at best as well as it's usually a good idea to avoid inline styles whenever possible. IsViewable as a boolean would be better, and you can still handle showing or hiding elements (in a different way).

How can we let our web designers code complex web apps without a server side language?

In my web development company, we have many designers who have the following dev knowledge and experience:
Client-side web languages (HTML, CSS, JavaScript)
Basic database design (how to create tables, relationships, etc), and
Basic SQL
The problem is that those guys don't know a server side language, such as C#. We want to give them an option to create web apps with their current knowledge.
Basically, they should be able to create data grids, add/edit forms, etc, without the use of a full server side language such as C# or PHP.
We don't want to create new huge new technologies here. We want a simple solution, that is easy to understand and maintain and possibly somewhat open source.
We thought about adding an extension to ASP.NET Razor, that looks something like this:
#DB(table="pages", where="id > 15")
<ul>
#while (row.Next()) {
<li>#row.Name</li>
}
</ul>
Is this a good solution, in terms of performance, design patterns, code style and security (SQL Injections)?
Is there anything open source for this?
Do you have any other ideas?
Here are some examples for a simple app that uses this style:
/apps/pages/index.html
#(DB.Select(table: "pages",
where: "id = ? and date > ?",
params: new[] { Request.QueryString["ID"], Request.QueryString["Date"] }))
<html>
<body>
<ul>
#foreach (var row in Model) {
<li>#row.Name</li>
}
</ul>
</body>
</html>
/apps/pages/create.html
#(DB.InsertOnPost(table: "pages",
fields: "name, description, date",
values: "?, ?, Now",
params: new[] { Request.Form["Name"], Request.Form["Description"] }))
#RedirectOnPost("/pages")
<form action="/pages/create" method=”post”>
<div>
<label for="name">Name</label>
<input type="text" name="name" />
</div>
<div>
<label for="description">Description</label>
<textarea name="description"></textarea>
</div>
</form>
/apps/pages/edit.html
#(DB.UpdateOnPost(table: "pages",
set: "name = ?, description = ?",
where: "id = ?",
params: new[] { Request.Form["Name"], Request.Form["Description"],
Request.QueryString["ID"] }))
#RedirectOnPost("/pages")
#(DB.Select(table: "pages",
where: "id = ?",
params: new[] { Request.QueryString["ID"] })
<form action="/pages/edit" method="post">
<div>
<label for="name">Name</label>
<input type="text" name="name" value="#Model.Name" />
</div>
<div>
<label for="description">Description</label>
<textarea name="description">#Model.Description</textarea>
</div>
</form>
IMHO
I have to say, UI guys are UI guys for a reason. This is where communication and understanding requirements comes in. Both parties should have a clear grasp on what needs to be done to get the end product complete. It should never be a concern to the guys on the front end how to get the information, just like you should never have to worry about which style sheet is being used when you're writing a service or making a view model.
If it's a matter of too much work load on the back end, it may be time to look at just cleaning things up or making things more concise, but not handing off DB access to someone who doesn't know what they're doing.
If you have this much concern over how they can and will access the data, shouldn't that be a red flag to start? It seems to me you'd rather invest weeks (and it will be weeks since you'll have to sandbox everything) in making it safely accessible instead of just plumbing it through for them.
Do requirements ever get you there 100%? No. You will have some back and forth (either UI needs something, or you do) but that's the name of the game. The good part is most of the time you can work in tandem (they are working on how it will look while you give them the pieces they need to wire it up).
I think you have several options here.
Get them to use node.js so they can use their JavaScript skills.
Get them to use Ruby on Rails, they will probably appreciate using a new technology, and you get a great framework to boot.
But probably more importantly, you should ask them what they think. You might be surprised.
Based on the data above, the fundamental conflicting datum is that you want them to be able to program something using a technology that they do not understand. In my experience, this is not a good idea. If no one on your team understands the ins and outs of server side development, you will end up with a low-quality product.
That said - the situation you are describing is quite common and this is thus a good question. My suggestion is that you should reorganize your team and workflow rather than trying to see how you can solve this by using a "simpler" technology (I put it in quotes because often attempts to make something simpler work for one set of problems, but as the requirements change those simplifications just start getting your way and it's then no longer simpler.)
Some specific options:
Hire one additional person with "backend coding" skillz and have them deal with all of the back end work. (Note that it's not all that important which backend language we're talking about - C#, PHP, Java, Python, etc. - the same principle applies - it's a different/more involved set of technical skills required as compared to doing UI scripting. And on the other hand, this person doesn't require any of the graphic design sense which a UI developer should have.)
Or, designate one of your existing team to bone up on these skills and while it will take them for them to learn - you at least have one specific person who will eventually be the guy who knows all about it.
Whoever this person is, should be in charge of selecting which framework to use. And they should do it with as much of an understanding of the particular problems specific to your project, etc.
Additionally, there are some technical approaches that could provide better separation. One idea is you could write API calls that provide JSON data which the UI people can then access using JQuery or similar tools. This way your backend code is all in one file and just returns data - making it more clear who is doing what. Example:
/api/some-data.php: (the "backend guy" edits this)
// do some work to get some data
$myData = ...;
// dump it out as JSON
print json_encode($myData);
/some-page-that-uses-data.html: (the "UI guy" edits this)
<!-- simple jQuery AJAX call -->
<script>
$(document).ready(function() {
$.ajax({ url:'/api/some-data.php' }).done(data) {
// do something to populate the page with the data...
};
});
</script>
(NOTE: You can use JSONP or CORS to get around cross domain problems if you run into that.)
Overall - instead of trying to have UI guys do work in an area they are not familiar with, separate the work so that people can specialize and each one does a good job on his/her part. You don't need a bunch of people to be server-side ninjas - but you need at least one...

Is there a benefit to using the HtmlHelper in MVC?

Is there a specific reason why I should be using the Html.CheckBox, Html.TextBox, etc methods instead of just manually writing the HTML?
<%= Html.TextBox("uri") %>
renders the following HTML
<input type="text" value="" name="uri" id="uri"/>
It guess it saves you a few key strokes but other than that. Is there a specific reason why I should go out of my way to use the HtmlHelpers whenever possible or is it just a preference thing?
Another benefit is that if your ViewData contains a value matching the name of the field it will be populated.
e.g.
ViewData["FirstName"] = "Joe Bloggs";
<%=Html.TextBox("FirstName") %>
will render
<input type="text" value="Joe Bloggs" id="FirstName" />
There are huge benefits:
It has overloaded methods to pre-populate the values (formatted, and safe for HTML) just like the ViewState.
It allows built in support for the Validation features of MVC.
It allows you to override the rendering by providing your own DLL for changing the rendering (a sort of "Controller Adapter" type methodology).
It leads to the idea of building your own "controls" : http://www.singingeels.com/Articles/Building_Custom_ASPNET_MVC_Controls.aspx
One thing is for consistency...I for one always forget the name attribute. Plus, you can extend the functions for your own projects. They're not called helpers for nothing!
The upside to using an abstraction layer is future proofing your code in a pluggable way. Maybe today, you create HTML 4 pages but tomorrow you want to create XHTML pages or XAML or XUL. That's a lot of changes if you just hard code the tags everywhere, especially if you've got hundreds of pages. If everything is calling this library, then all you've got to do is rewrite the library. The downside is that it is usually considered to be slightly less readable by humans. So, it most probably increases the cognitive demand on your maintenance programmers. These advantages and disadvantages really have nothing to do with MVC.
It actually auto populates your textbox based upon first your ViewData.Model.uri and second by ViewData["uri"]. Doing it manually you'd need to do <input value="<%Html.Encode(ViewData.Model.Uri"%>" />
I haven't been doing MVC too long, but I've already written some extension methods to generate menu tabs based on Html.ActionLink. It allows me to be consistent with my usage and, if I decide to change how my CSS menus work, only modify a single method to output the new tab format.
The other use that I have made of them is in conditional output using ViewData to supply values to the controls.

Resources