SAPUI5 - complex model binding - binding

I have this json model:
model/data.json
{
"orders" : [
{
"header" : { "id" : "00001", "description" : "This is the first order" },
"items" : [
{ "name" : "Red Book","id" : "XXYYZZ" },
{ "name" : "Yellow Book", "id" : "AACCXX" },
{ "name" : "Black Book", "id" : "UUEEAA" },
]
},
{
// another order with header + items
},
.....
]
}
and I'm assigning it onInit to the view, like this:
var model = new sap.ui.model.json.JSONModel("model/data.json");
sap.ui.getCore().setModel(reqModel);
I'm trying to display a list of orders in the first view (showing the id), like this:
var list = new sap.m.List({
id: "mainList",
items: []
});
var items = new sap.m.ActionListItem({
text : "{id}",
press : [ //click handler, onclick load the order details page ]
});
list.bindItems("/orders", items);
.... // add list to the page etc etc
What I cannot do, is connect each order to its header->id.. I tried
text: "/header/{id}"
text: "{/header/id}"
in the items declaration, and
list.bindItems("/orders/header", items)
in the list binding, but none of them works.. The id value is not displayed, even though a "blank" list item is shown..
Any idea? What am I doing wrong?
Thank you

The solution was one of those I tried (but I don't know why it didn't work at that time)
text: "{/header/id}"

The ListItem acts as a Template for a list/array of objects. That's why you bind it against an array structure in your data:
list.bindItems("/orders", itemTemplate)
That makes bindings of the ListItem relative to /orders and therefore your item should look like this without leading '/' (absolute paths would look like this /orders/0/header/id asf.):
var itemTemplate = new sap.m.ActionListItem({
text : "{header/id}",
press : [ //click handler, onclick load the order details page ]
});
Not quite sure how you made it work the way you have shown... May be it's not as picky as I thought.
Btw: For whatever reason the ResourceModel builds an exception of that syntax. You can always omit the leading '/' when dealing with ResourceModels (probably because they do not allow nested structures).
BR
Chris

Cannot add comments yet, therefore an answer to you solved Problem, that could answer the initial problem. (And inform People using that example in any way)
In the current code listing you use the variable "reqModel" to set the model, but the variable with the model in it is named "model" in the line before. Maybe that was the first reason why both of your examles would not work?
Perhaps this error was cleared on rewriting some passages while testing.
greetings! -nx

Related

ElasticSearch writing query for priority search

I am new to elastisearch and I just set it up and tried default search. I am using elasticsearch rails gem. I need to write custom query with priority search (some fields in table are more important then others, etc. title, updated_at in last 6 months...). I tried to find explanation or tutorial for how to do this but nothing seems understandable. Can anyone help me with this, soon better.
Never having used the ruby/elasticsearch integration, it doesn't seem too hard... The docs here show that you'd want to do something like this:
client.search index: 'my-index', body: { query: { match: { title: 'test' } } }
To do a basic search.
The ES documentation here shows how to do a field boosted query:
{
"multi_match" : {
"query" : "this is a test",
"fields" : [ "subject^3", "message" ]
}
}
Putting it all together, you'd do something like this:
client.search index: 'my-index', body: { query: { multi_match : {
query : "this is a test",
fields : [ "subject^3", "message" ]
} } }
That will allow you to search/boost on fields -- in the above case, the subject field is given 3 times the score of the message field.
There is a very good blog post about how to do advanced scoring. Part of it shows an example of adjusting the score based on a date:
...
"filter": {
"exists": {
"field": "date"
}
},
"script": "(0.08 / ((3.16*pow(10,-11)) * abs(now - doc['date'].date.getMillis()) + 0.05)) + 1.0"
...
I have done in php, Never used the gem from Ruby on rails. Here you can give the priority for the fields using the caret (^) notation.
Example:- Suppose if we have fields namely name, email, message and address in table and the priority should be given for the name and message then you can write as below
> { "multi_match" : {
> "query" : "this is a test",
> "fields" : [ "name^3", "message^2".... ] } }
Here name has 3 times higher priority than other fields and message has got 2 times higher priority than other fields.

Update field of embedded documents on multiple Mongoid documents [duplicate]

This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 5 years ago.
I recently started using MongoDB and I have a question regarding updating arrays in a document.
I got structure like this:
{
"_id" : ObjectId(),
"post" : "",
"comments" : [
{
"user" : "test",
"avatar" : "/static/avatars/asd.jpg",
"text" : "....."
}
{
"user" : "test",
"avatar" : "/static/avatars/asd.jpg",
"text" : "....."
}
{
"user" : "test",
"avatar" : "/static/avatars/asd.jpg",
"text" : "....."
}
...
]
}
I'm trying to execute the following query:
update({"comments.user":"test"},{$set:{"comments.$.avatar": "new_avatar.jpg"}},false,true)
The problem is that it update all documents, but it update only the first array element in every document. Is there any way to update all array elements or I should try to do it manually?
Thanks.
You cannot modify multiple array elements in a single update operation. Thus, you'll have to repeat the update in order to migrate documents which need multiple array elements to be modified. You can do this by iterating through each document in the collection, repeatedly applying an update with $elemMatch until the document has all of its relevant comments replaced, e.g.:
db.collection.find().forEach( function(doc) {
do {
db.collection.update({_id: doc._id,
comments:{$elemMatch:{user:"test",
avatar:{$ne:"new_avatar.jpg"}}}},
{$set:{"comments.$.avatar":"new_avatar.jpg"}});
} while (db.getPrevError().n != 0);
})
Note that if efficiency of this operation is a requirement for your application, you should normalize your schema such that the location of the user's avatar is stored in a single document, rather than in every comment.
One solution could be creating a function to be used with a forEach and evaling it (so it runs quickly). Assuming your collection is "article", you could run the following:
var runUpdate = function(){
db.article.find({"comments.user":"test").forEach( function(article) {
for(var i in article.comments){
article.comments[i].avatar = 'new_avatar.jpg';
}
db.article.save(article);
});
};
db.eval(runUpdate);
If you know the indexes you want to update you can do this with no problems like this:
var update = { $set: {} };
for (var i = 0; i < indexesToUpdate.length; ++i) {
update.$set[`comments.${indexesToUpdate[i]}. avatar`] = "new_avatar.jpg";
}
Comments.update({ "comments.user":"test" }, update, function(error) {
// ...
});
be aware that must of the IDE's will not accept the syntax but you can ignore it.
It seems like you can do this:
db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...})
So if you have a small known number of array elements, this might be a little easier to do. If you want something like "comments.*.avatar" - not sure how to do that. It is probably not that good that you have so much data duplication tho..

sapui5 table shows only the same record [duplicate]

This question already has an answer here:
OData Model Not Working
(1 answer)
Closed 20 days ago.
I have created a webservice and trying to bind data using oData protocol in SAPUI5.
I have created a table:
createContent : function(oController) {
jQuery.sap.require("sap.ui.table.Table");
//Create table control with properties
var oTable = new sap.ui.table.Table({
width : "100%",
rowHeight : 50,
title : "Lst of Items",
selectionMode : sap.ui.table.SelectionMode.None
});
oTable.addColumn(new sap.ui.table.Column({
label : new sap.ui.commons.Label({
text : "PO Number"
}),
template : new sap.ui.commons.TextView({
text : "{PoNumber}"
}),
}
));
oTable.addColumn(new sap.ui.table.Column({
label : new sap.ui.commons.Label({
text : "Item"
}),
template : new sap.ui.commons.TextView({
text : "{PoItem}"
}),
}
));
//Filter values for a certain PO
var aFilter = [];
aFilter.push( new sap.ui.model.Filter("PoNumber", sap.ui.model.FilterOperator.EQ, "4500000043") );
oTable.bindRows({
path: "/PurchaseOrderItemCollection",
filters: aFilter
});
return oTable;
}
The output should be as follows:
PONumber POItem
4500000043 0010
4500000043 0020
But what I get is:
PONumber POItem
4500000043 0020
4500000043 0020
So it shows the last item twice and doesn't show the first item. If I put a break point in my web service code then it is populated correctly.
The data model is created in the following way:
var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, false, "user", "passw");
sap.ui.getCore().setModel(oModel);
I have encountered this. Problem is with your data model. Ensure that for the entity both PO number and PO item are marked as keys. Refresh any metadata cache, ensure that both properties appear as keys and try again. It should work.
Thanks
Krishna
My understanding is every entity/entry in the collection should have a unique id <entry><id>...</id></entry>.
And in my case, the returned collection had no ids set for the entities. So the bound ui element finds multiple objects with same id (in this case empty id) and ends up displaying value which it finds the last.
The same should apply even if the id is same across all entities.
Hope it helps, if you have not already found what the problem is.
Thanks,

Backbone.js why a model from a collection doesn't have url set?

I am still relatively new to Backbone. I'm just beginning to get a sense of how it works. I 've been using Rails for a while and it's what is giving me some hint at times of using Backbone. so here goes:
Simple, I have a Company model over in Rails say I do in javascript console
companies = new Backbone.Collection();
companies.url = '/companies';
companies.url; // '/companies'
companies.fetch();
company = companies.at(0);
company.url
The last line, "company.url" doens't return what I expect, what I expect is something like '/companies/12345' so that when I update company and decide to save it, it will know where to "put" to.
So does that mean that everytime I want something saved, I have to save on the whole collection?(!)
I would take a look at what company.url() is returning. Saving the whole collection should not be necessary.
I was trying your problem, and found that the models are not getting an id to it. So the url method on the models is not working. So i think you need to put your collections like below (what i tried)
cltn = Backbone.Collection.extend({
model:modelName,
parse:function(res){
var i = 0;
var itms = _.map(res.items, function(o){
o.id = ++i;
return o
})
return itms;
}
});
cltnInst = new cltn();
cltnInst.url="/combodata.json?";
cltnInst.fetch();
Then in your firebug type the below codes.
cltnInst.url; // this is a string props. output will be "/combodata.json?"
cltnInst.at(0).url() // this is a method props output will be "/combodata.json?/1"
combodata.json will be of this format
{
"identifier": "title",
"items": [
{
"title": "A",
"tag": "htmlcss",
"date": "today"
}, ...
]}
Please correct me if my answer is wrong.
I have actually made a mistake in the step where I make an attempt to create a new companies collection.
So instead of
var Companies = new Backbone.Collection()
I should really do something like this:
var Companies = Backbone.Collection.extend({
model: Company,
url : '/companies'
});
var Company = Backbone.Model.extend();
var companies_collection = new Companies()
companies_collection.fetch()
companies_collection.models[0].url() // '/projects/123'

How do I avoid a circular reference while serializing Entity Framework class

I have an MVC-3 (RC1) application using Entity Framework 4.
I wish to return a JSON object from a controller action. This object is referenced by other objects, which obviously return the reference.
I thus receive the following circular reference error:
Server Error in '/' Application.
A circular reference was detected
while serializing an object of type
'Application.Models.ReferenceObject'.
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.
Exception Details:
System.InvalidOperationException: A
circular reference was detected while
serializing an object of type
'Application.Models.ReferenceObject'.
NB: Application & ReferenceObject are obviously replacements for the actual namespace / object.
According to Stack Overflow: Circular reference exception when serializing LINQ to SQL classes, this can be overcome using JSON.Net; however I would like to avoid this and instead try to exclude the offending reference properties from the object being serialized.
What do I mean?
I want to do something like this:
IList<ReferenceObject> list = Repository.GetReferenceObjects();
return Json(list.**<method>**("ObjectsReferencingThis"));
where **<method>** is some method that does the opposite to the ObjectQuery(Of T).Include method and ObjectsReferencingThis is the property that is causing the circular reference.
NB: I do not wish to remove these properties or create POCOs as this only affects the Json serialization.
Anyone able to help please?
:)
I had a similar problem when worked on one of my previous project.
Here is what I ended up doing:
IList<Product> list = Repository.GetProducts();
var collection = products.Select(product => new
{
id = product.Id,
name = product.Name,
detailUrl = product.DetailUrl,
imageLargeUrl = product.ThumbNailUrl,
tagtitle = product.Name.ToUpper(),
tagheader = "Words our cherished patrons use to describe this product",
tagwords = from tag in product.Tags group tag by tag.Name into words select new { name = words.Key, weight = words.Count() }
});
var result = new {id = inquiry.Id, products = collection, };
return this.Jsonp(result);
Here is how the result Json would look like:
{
"id" : 2,
"products" : [{
"id" : "3605970008857",
"name" : "TITLE1",
"detailUrl" : "http://www.urlhere.com",
"tagwords" : [{
"name" : "roses",
"weight" : 1
},
{
"name" : "cotton",
"weight" : 1
},
{
"name" : "happy",
"weight" : 1
}]
},
{
"id" : "3605970019891",
"name" : "TITLE2",
"detailUrl" : "http://www.urlhere.com",
"tagwords" : []
}],
}
You can also add any other properties from you referenced objects to the result as you wish,to be shown in your Json object :)
I made a very trivial solution which is not recommended if you have very big list
letters=UserOperations.GetDepartmentLettersForSecretary(pageNumber, pageSize,(Session["User"] as User).DepartmentID.Value, (Session["User"] as User).ID);
foreach (Letter letter in letters)
{
letter.LetterStatus.Letters = null;
}
the problem of circular reference in my case is in LetterStatus.Letters
so I Iterated through the list and assigned it to null
as I told you its not recommended if you have very big list

Resources