In a work around I've used in the past, I've used the id field to pass an additional parameter that I needed. But I need to pass three parameters through a remoteField and now am presented with the fact I need to find a way to pass these parameters:
<g:remoteField action="updateFields" update="theDiv" id-"${personInstance.id}" paramName="search" name="updateFields" value="" />
Need: The search field (search), the person id (id), and now I need the company the person works for (c_id).
I can do something like this:
<g:remoteField action="updateFields" update="theDiv" id-"${personInstance.id}" paramName="search" name="updateFields" value="" params="${[c_id:c_id, search:/'+this.value+/']}"/>
If I try to obtain the search value with the params, the search field is now '+this.value+'. Can I just pass the object search field as an addition param in the map (like above) by referencing this.value? If so, what am I doing wrong, since my gsp doesn't load.
Edit
My current work around is to tie both IDs in a ID field, split by a delimiter and then broken into an array once it reaches the controller (obviously not ideal!)
Although I don't use remoteField, I do use remoteFunction frequently and have found I can use multiple javascript based variables directly with the 'params' parameter. E.g.
<script>
function someJSFunction(id1,id2,id3) {
<g:remoteFunction action="ajax_function" params="{id1:id1,id2:id2,id3:id3}" update="someDiv"/>
}
</script>
Hope that helps.
Related
I'm including dynamic content to a view using a custom Thymeleaf attribute processor that simply adds additional nodes while processing the attribute itself.
The code I use is very similar to the one below:
final Template template = arguments.getTemplateRepository().getTemplate(
new TemplateProcessingParameters(arguments.getConfiguration(), "name-of-a-view", arguments.getContext()));
final List<Node> children = template.getDocument().getChildren();
// Add to the tree.
for (final Node node : children) {
element.addChild(node);
}
This works fine, but breaks when the included nodes contains forms that use th:object and th:field.
I put the model I need inside the node variable map and in fact th:object does find and retrieves the object, but th:field does not seems to care and breaks with a
Neither BindingResult nor plain target object for bean name 'model' available as request attribute
From my understanding (step-by-step debugging), it seems to me that th:field only search for the model in the request context.
Am I missing something here?
Thank you in advance.
No, you're spot on. I'm still not sure why the binding is different for th:field than other th: attributes, but it definitely works differently. Essentially, you can't use th:field unless your th:object is on the model. The workaround is to stop using th:field and just specify your input attributes manually, like:
<form action="#" th:action="#{/process}" th:object="${objectFromList}" method="post">
<input type="text" id="fieldName" name="fieldName" th:value="*{fieldName}" />
</form>
I realize this post is old. Hopefully, this will help someone who is running into this quirk.
I have a small problem.
I want to have dropdown list with some objects. After clicking on one I want to add it to list with textfield for naming it. I don't want to limit quantity of this fields. I want to receive in controller ID (stored in dropdown list) and name (given by user) for each selected item. How can I do it?
I was thinking about storing it in some fields as a text, and parsing in cotroller but I think it's not elegant.
EDIT.
Ok, Thansk for your help, but it's not working for me correctly.
I generate html like this:
<input type="hidden" value="96" name="Inputs[0].Key">
<input type="text" name="Inputs[0].Value">
In my controller I'm receiving this dictionary. The problem is that quantity of elements is correct, but all values are null. What is wrong here?
The best way to go about this is by using array-style model binding.
So, for each element you wish to name you create a hidden field to store the drop down value plus a text field to store the user-given name. You name them as follows:
<input type="hidden" name="element[0].Key" /><input type="text" name="name[0].Value" />
increasing the index value each time. This is easily achieved with a bit of JavaScript. You then create an action method which takes a KeyValuePair<string, string>[] as a parameter. You will then be able to parse through your values no problem with a loop or LINQ expression.
Use IEnumerable<KeyPairValue<string,string>> MySelectedItem = new List<KeyPairValue<string,string>>(); on model, and when adding it to the list, name it like an array:
MySelectedItem[1].Key, MySelectedItem[1].Value, MySelectedItem[2].Key...
(I haven't tested this, but it should work)
Edit: check out this blog post with better explanation on how to do it: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
I've been trying to debug an issue and I pinned pointed it down to this scenario:
When the statement Html.TextBox("ID", "What the heck..") is executed, I expect it to render:
<input id="ID" name="ID" type="text" value="What the heck.." />
But I get a Guid as its TextBox value such as so:
<input id="ID" name="ID" type="text" value="2e369d2c-071d-4733-8382-cc9e77d0b912" />
Why is Asp.net MVC outputting Guids? I'm not overriding asp.net mvc's framework methods. Please refer to the screenshot.
Update:
Here's another screenshot using Html.Hidden() instead of Html.TextBox(). I couldn't use Html.HiddenFor() directly into the Watch window because HiddenFor() uses lambdas.
#Eric Petroelje and #TLS: You two are correct. TextBox() and Hidden() is retrieving ID's value from the POST variables and not from the current Model or the function's value parameter. Though, I've expected different from HiddenFor() and TextBoxFor(). I expected it to get its value from the POST'ed variables only if it cant get it from the current Model. How can I achieve this?
Maybe you have a POST variable named ID that is a GUID? If that's the case, the HTML Helper method will use that POST value. If no POST value is present, it will fall back to the value in the model.
You are correct that Html.TextBox("ID", "What the heck..") is expected to output the attribute values that you give in your first example; however, if you are using the Html.TextboxFor method, then you're using a MVC Helper that dynamically loads the value of the ID property and places that into the value attribute in the HTML. When you use the Html.TextboxFor method, your second example is the expected HTML output if your ID property is a Guid.
I have something like:
<input type="text" name="TerrMng" id="TerrMng"/>
in HTML. What is the equivalent of the above using #Html.Display?
I tried using: #Html.Display("TerrMng", TerrMng)
but was not successful. Note that I like to use #Html.Display but not sure how to translate the ID value so that it shows up.
The Display method is not for creating input boxes. You'd want to use:
#Html.TextBoxFor(m => m.TerrMng);
or the templated helper method:
#Html.EditorFor(m => m.TerrMng);
I'm assuming that you want to use modelbinding. If not, if you really just want to use a helper to simply make an input tag, use:
#Html.TextBox("TerrMng");
This would be sent to the client:
<input id="TerrMng" type="text" value="" name="TerrMng">
The first 2 methods above would result in the exact same html, if model.TerrMng was "" or String.Empty. If for some reason you don't want the value attribute, you'll need to type it out yourself.
This should do the trick if you are just wanting to display the data and not allow the user to edit the information.
#Html.DisplayFor(m => m.TerrMng);
Edit:
what-is-the-html-displayfor-syntax-for is another question on stackoverflow that may give you some more guidance.
Edit:
TerrMng does not exist on PageLoad so you cannot use the Html.Display in that way. You need to create it and fill its value with the value received from the jQuery. In this case where you would have to do the following:
HTML
#Html.Display("TerrMng"); // This creates the label with an id of TerrMng
jQuery
$("#TerrMng").val(TerrMng); // This puts the value of the javascript variable into the label
You could try something based on this. This is not exact but you could get some idea.
#Html.TextBoxFor(yourmodel => model.yourModelFieldname, null)
#Html.Display() is used instead of #Html.DisplayFor() when your model is not known at compile time, or if you prefer to work with strings, rather than with strong types. For example, these 2 are equivalents (given that your model is some class):
#Html.DisplayFor(m => m.MyProperty)
and
#Html.Display("MyProperty")
But the additional cool feature of the Display() method is that it can also do the lookup in the ViewData, and not just in your Model class. For example, here is a way to display the HTML for the property on a random object, given that we know it has a property named "Blah" (the type of the object doesn't really matter):
#{ ViewData["itsawonderfullife"] = SomeObject; }
<div>#Html.Display("itsawonderfullife.Blah")</div>
This way, we are telling HtmlHelper to look into the ViewData, instead of our Model, and to display the property Blah of a given SomeObject.
In one of the applications I am building I have constructed a very flexible attribute-based system for describing products in my database wherein each product can have an indeterminate number of attributes assigned to it with each attribute having a single "type". So, for example, one attribute type might be "Category" and the value assigned to a single attribute would be something like "Trucks". There are no restrictions on the number of attributes assigned to a given product and because the attributes and attribute types are stored in the database alongside the products, my application does not know ahead of time what any of them will be.
One of the features of the options for a given attribute type is whether or not it is "searchable". In the event of an attribute being searchable I can then use its value paired with its type name to search/filter my products. So, for example, a user might want to return all products having the attribute type "Category" equal "Trucks" and attribute type "Color" equal "Red". Nothing too unique there.
The trouble I am dealing with is that because my system does not know ahead of time what my attribute type names are, I cannot easily create an action method accepting parameters in a readable format like string category or string color. As a solution I have made use of the DefaultModelBinder's support for binding to a dictionary. With this approach I need only format my field names in the correct structure, and then my action method can accept an IDictionary<string,string> parameters. This all works fairly well, but it makes for some really nasty URLs when the user is performing a link-based filter by a single parameter, i.e. "See more Products in Category Trucks". With the DefaultModelBinder binding to a dictionary requires that your field naming pattern resembles the following:
<input type="hidden" name="parameters[0].Key" value="Category" />
<select name="parameters[0].Value">
<option value="Trucks">Trucks</option>
<option value="Compacts">Compacts</option>
<option value="SUVs">SUVs</option>
</select>
<input type="hidden" name="parameters[1].Key" value="Manufacturer" />
<select name="parameters[1].Value">
<option value="Ford">Ford</option>
<option value="Toyota">Toyota</option>
<option value="Honda">Honda</option>
</select>
Not only is this incredibly verbose, but it also somewhat frustrating due to the fact that each Key/Value must contain an ordinal index in the field name. Although this is acceptable for a POST form, it is not particularly ideal in a GET URL because we end up with URLS resembling ?parameters[0].Key=Category¶meters[0].Value=Trucks¶meters[1].Key=Manufacturer¶meters[1].Value=Ford. Not only is this ugly, it is very limited in its implementation because any modification to the URL could potential destroy the entire result set (if the user wanted to just search by the second parameter via modifying the URL they would have to remove the first parameter and renumber the whole collection appropriately).
What I am looking for is a better way to handle this kind of situation. Ideally I'd like to simply have a querystring value ?Category=Red and filter accordingly, but then my action method doesn't know if there actually is a "Category" parameter to bind to. Is there any in between that would allow me to have cleaner querystring parameters that wouldn't make for such awful URL structures?
I was thinking about possibly building my own custom ModelBinder, but I'd like to avoid that if there's another way.
I much prefer your "clean" URIs: ?Category=Red. So let's start there and see how it could work.
You can load up all the categories at runtime, right? Off the top of my head:
IEnumerable<string> allCategories = Categories.GetAll();
var usedCategories = Request.QueryString.AllKeys.Intersect(allCategories);
var search = from c in usedCategories
select new
{
Key = c,
Value = Request.QueryString[c]
};
You could use this as-is, or make a custom model binder. In either case, it's not a lot of code.