In my XSOData service I have an entity based on calculation view with input parameters. I can to set these parameters as constants in my XML view, i.e.
<List items="{dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=2)/Results}" >
<StandardListItem
title="{dicts>NAME}"
/>
</List>
and it will work fine.
But how I can set parameters p_dict_name and p_rec_id dynamically? I tried to use expression bindings to get values for parameters from another model (something like this: <List items="{= ${dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=${DictUIProps>/parentId})/Results} }" >) but with no luck. As I understand, expression bindings won't work. Is there any other way?
As far as I'm aware you can't do the aggregation binding dynamically through XML. At least not in the versions I have used and I have to admit I haven't re-checked in a while. The string never gets interpreted for inner bindings before it's applied to the model.
The way I do this is through the controller:
<List id="myList" />
and in your controller (onBeforeRendering or onPatternMatched or wherever your model and view are known to the controller):
this.getView().byId('myList').bindItems({
model: 'dicts',
path: `{/AncParams(p_dict_name='${p_dict_name}',p_rec_id=${p_rec_id})/Results}`,
template: new sap.m.StandardListItem({
title: '{dicts>NAME}'
})
});
you can use the getModel('dicts').createKey function to generate the path name which is a little cleaner I suppose.
This is the way to apply dynamic filters as well, In case you ever build those.
Related
Is it possible to use a URL parameter as a property binding in UI5?
My problem is that I want to have different OData collections placed in the same UI5 aggregation. For example let's say I've "/Car("Mustang")/parts" and "/Car("Whatever")/parts". Both of them can be placed in the same view.
The application's URL contains the keyword like http://something/#/carMustang. This URL is coming from a routing pattern like "car{carHandle}".
How am I supposed to do stuff like this:
<List items="{/Car({carHandle})/parts}">
<StandardListItem title={someProperty}>
</StandardListItem>
</List>
So what would be the best practice to do this? I would like to avoid nasty fiddles in the controller.
In your view:
<List id="parts" items="{parts}">
<StandardListItem title="{someProperty}"/>
</List>
In your controller code which reacts on matched routes:
var carHandle = event.getParameter("carHandle");
this.byId("parts").bindObject("/Car/" + carHandle);
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.
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.
Having just spent two amazingly frustrating hours formatting some hidden fields to bind properly to action method parameters -- the second time I've had this experience in the last week -- I'm now very curious as to why the MVC architects chose the particular binding convention that they did for lists (and dictionaries) of objects.
Here's my painfully gathered understanding of the format expected by the default binding engine. In my example I want to bind to a List, where the CustomClass type exposes a public property called PropertyName:
<input type="hidden" name="prefix[idx].PropertyName" value="PropertyName[idx] Value" />
prefix is the ViewDataDictionary.TemplateInfo.HtmlPrefix, if one has been defined.
I find it deeply counter-intuitive to start the reference to something with the indexing information (i.e., the [idx] piece). I also find it disturbing that nowhere in this construct do I make reference to the name of the action method parameter to which I'm binding. That seems to be in direct contrast to what happens with, say, a primitive model property:
<input type="hidden" name="Text" value="something" />
public ActionResult SomeActionMethod( string Text )...
I understand I can roll my own model binder in MVC. That doesn't seem like a profitable use of my time, although spending hours trying to puzzle out the correct format for hidden fields isn't profitable either :), so maybe I'll try that. I also know that I can let MVC do all the heavy lifting by creating a type template using #Html.HiddenFor(), and then outputting instances of CustomClass though a simple partial view that has CustomClass as a model and the single line #Html.DisplayForModel(). But that seems like going the long way around the barn, too. Besides, there are limitations to using the #Html.Hidden helpers (e.g., they "helpfully" raid the cache after postback to fill in values, so writing #Html.Hidden("fieldname", value) doesn't guarantee value will end up being output -- you may get the older value in the cache instead, which was another hour-long annoyance today).
But I'm mostly just curious why this format was chosen. Why not something more C/C++/C#/VB like:
<input name="prefix.ParameterName.PropertyName[idx]" />
Edit:
Good point on where I put the index parameter in my example. You're right, the property isn't indexed, the containing class is.
However, that doesn't change the basic situation. Why isn't the syntax something like:
<input name="prefix.ParameterName[0].PropertyName" />
The standard syntax ignores the parameter name with collections of custom types, and "guesses" the custom type from the property names. That's bizarre...so there must be a story or choice behind it :).
Actually, it makes perfect sense. The index is into the collection, not the property. You don't have a collection of PropertyName, you have a Collection of CollectionName[] that has a PropertyName.
To put this another way:
public class Foo { public string Bar { get; set; } }
var foos = List<Foo>();
for (var i = 0; i < foos.Length; i++)
{
var prop = foos[i].Bar; // This is the important bit
}
That's exactly what happens in the model binder.
When the model binder deserializes the post values, it has to know which collection to insert the values into, and it has to know what index each item is for. So it has to know to create a Collection of Foos, of x number of items, and which indexes each Bar is associated with.
Please pardon this newbie question...
In Grails, if I want a partial to be embedded in a layout so that it appears globally, which requires live data, let's say a list of categories, where is the best place to pull the category data to feed it into the view?
I realize this is a very basic question, but I haven't seen this covered in any tutorials yet.
I started this as a comment to Bill James's answer but I figured it might be longer. Bill suggeseted using groovy code inside ${} to make the template (called partial in Rails) work globally:
<g:each in="${ Category.findAll() }" var="cat" />
But, you should not just add code if you dont feel like it might mess up your tidy xml/html. You can always put it in a closure inside a TagLib and thus make it a Tag. The closure must have no parameters, or an 'attr' parameter, or an 'attr' and 'body' parameters but other signatures are invalid.
class CustomTagLib {
static namespace = 'cus'
def categories = { attr, body ->
g.each( in: Category.findAll(), var: attr?.var ?: 'categories' )
}
}
Then you can use that tag into the template with the namespace you chose:
<cus:categories />
Personally I prefer using tags since most of the time it is a reusable code, so it's better for not violating the DRY principle.
You want to put it in grails-app\views\layouts\main.gsp. That's the default layout that most generated code (and likely most examples that you'll see) will use.
Check out the sitemesh section of the grails documentation.
I think you're trying to ask... "How do I feed the category data to the view when I don't know which action caused the page to render, so the action can't add the data to the model?" If that's so, you can use Groovy code directly in the ${} block, such as:
<g:each in="${ Category.findAll() }" var="cat" />
Note that findAll is added to every Model class, and can be called statically (via the classname, not an instance).
Hope this helps