UI5: Why is the formatter called a second time with a 'null' value? - combobox

I'm using a XML-Fragment defining a ComboBox where I want to add some core:CustomData with a value returned by a formatter. The formatter is called the first time when the fragment shows up and a second time when I open the dropdown list of the combobox. First time I get a single entry(from entries) from the model as expected. At the second call the parameter is null.
What am I doing wrong?
'myModel' is a static json model loaded via manifest.json:
{
"entries": [
{
"title": "first entry",
"hide": false,
"id": 1
},
{
"title": "second entry",
"hide": true,
"id": 2
}
]
}
The ComboBox defined inside a FragmentDefinition inside a Popover:
<ComboBox id="xys" selectedKey="{myModel>/aKey}" value="{myModel>/aValue}"
items="{myModel>/entries}">
<core:ListItem key="{myModel>id}" text="{path: 'myModel>', formatter: '.entryTextFormatter'}" >
<core:customData>
<core:CustomData key="hide-item" value="{path: 'myModel>', formatter: '.hideItemFormatter'}" writeToDom="true"/>
</core:customData>
</core:ListItem>
</ComboBox>
And the formatter code looks like:
/* Test cases */
entryTextFormatter: function(entry) {
return entry.title;
},
hideItemFormatter: function(entry) {
if(entry && (entry.hide == true)) {
return "true";
} else {
return "false";
}
},
Edit: Note! If using the same formatter for the CustomData and the ListItem it is only called twice for the CustomData.
Does anyone has an idea why the formatter gets null as parameter the second time?

Related

Why is my array.find and array.filter returning empty

I have an Array that looks like this
resultList: any[];
this.resultList = [
{
"id": "14e6f101-f8e8-4914-930f-cbba7a9c5328",
"value": "Dream Inc."
},
{
"id": "9a16c1c0-68f3-498a-b968-61849ccc2a21",
"value": "Dressing, Inc. ABC LOREBOX SERVICES"
},
{
"id": "919b3cdb-c5fb-40c8-b88f-6c7f44f8446f",
"value": "Dresson-Brand Company"
}
]
I am having a hard time trying to retrieve the second item (index 1) by using the value. I can get the other two items by value but the second item returns undefined
code I am using
search(value: any) {
//value coming in
//Dressing, Inc. ABC LOREBOX SERVICES
console.log('*** value to search ***', value);
var foundObj = this.resultList.find(p => p.value == value);
console.log('*** foundObj ***', foundObj);
}
foundObj comes back empty and same results when I do a filter. Any idea's what is wrong with that string that it can't be found? It seems I can get any other string (this is a dynamic array) but this one.
The issue came from the dataList I was using. In the element I was missing the 'value' attribute. Once I added that the spaces were no longer removed and my filtering was able to pick it up.

Resolving simple references in a spreadsheet structure. Is this a linked list problem?

I have this job test task where I am need some help.
I have to somehow dynamically access the value in the data stucture below, through references. To this point I used loops and indexOf() in an ordered alphabet and numbers. indexOf("B") in alphabet is [[ 1 ]], indexOf(1) is [0] for the two dimensional array.
Here "B1" is referencing "C1", "C1" references "D1" .. to "H1" and when "H1" points to the text "Last", all of the formulas should turn into the same value - the text "Last".
But how? Been breaking my head for a couple of hours and remembered linked lists, but so far have no clue how to implement them. How can I achieve this?
{
data: [
[
{ reference: "B1" },
{ reference: "C1" },
{ reference: "D1" },
{ reference: "E1" },
{ reference: "F1" },
{ reference: "G1" },
{ reference: "H1" },
{ text: "Last" },
]
],
id: "job-20"
}
It looks like you need to work with a spreadsheet type of data structure, and need to recalculate cells based on the formulas they have.
You can use recursion for that.
The base case happens when you arrive at a cell that has no reference. In that case the text of that cell can be returned to the caller. And that caller will assign that text to the cell it was looking at, and also returns that to their caller...etc.
function get(reference) { // return the cell object at the given reference
return data[reference.slice(1)-1][reference.charCodeAt() - "A".charCodeAt()];
}
function resolve(cell, visited=new Set) {
// Have we found a cell with just text? Then return that to caller
if (!("reference" in cell)) return cell.text;
// Did we already meet this cell before? Then we are running in circles!
if (visited.has(cell)) return "Circular Reference!";
// Make a recursive call to know what the text should be
cell.text = resolve(get(cell.reference), visited.add(cell));
delete cell.reference;
return cell.text; // Return this value also to the caller
}
function calculate(data) {
// Get to each cell object...
for (let row of data) {
for (let cell of row) {
resolve(cell); // And update its text property by following references
}
}
}
let data = [
[
{reference: "B1"}, {reference: "C1"}, {reference: "D1"}, {reference: "E1"},
{reference: "F1"}, {reference: "G1"}, {reference: "H1"}, {text: "Last"},
]
];
calculate(data);
console.log(data);
It should be noted that in a real spreadsheet the references (formulas) are not deleted during such a recalculation. The cell will have both the text and the reference, so that when a cell's text is updated, all other dependent cells get their own text updated accordingly again.

filter array elememts to add to listView

I am reading from my firebase database, which holds nested data in the following format which I want to add specific elements of to a listView;
group {
subgroup {
index[0]{
name: "Tom"
message: "hello"
}
index[1]{
name: "Dave"
message: "goodbye"
}
index[2]{
name: "Katie"
message: "morning"
}
}
}
What I want to do is add the name and message property to a listView in my app, an array is created when my app is launched with data from firebase, so I need to check for the name property and add to the list view when applicable.
I have used for loops and image visibility to display markers on a calendar, would a similar approach of looping through the array be the best option to create the list? I do need to create the list on specific dates on the calendar with 1 or more username entry in the same method.
By looping using the following code in my console shows what i want. yet i am struggling to translate into my list model, If i am just adding the name the below code works, but adding both to my list isn't working. My code is;
var nameArr = (JSON.stringify(value))
var parseData = JSON.parse(nameArr);
for(var index in parseData)
console.log("nameParse: ", parseData[index].name, ":", "detailsParse: ", parseData[index].message)
ListView {
id:eventListView
spacing: 4
clip: true
anchors.fill: parent
anchors.margins: 10
model: ListModel {id: model }
Component.onCompleted: {
model.clear();
var list = parseData;
for(var i in list)
model.append({"name": list[i].name, "details": list[i].message});
}
delegate: Label {
id: nameLabel
text: modelData.name
}
Label {
id: timeLabel
text: modelData.message
}
}
Javascript array could be used as a data source in this way:
ListView {
anchors.fill: parent
property var group: {
"subgroup": [
{
"name": "Tom",
"message": "hello"
},
{
"name": "Dave",
"message": "goodbye"
},
{
"name": "Katie",
"message": "morning"
}
]
}
model: group.subgroup
delegate: Text { text: modelData.name }
}

Update array in mongo and upsert

I'm trying to update an array within a document and it works correctly, but when I want to add a new element with upsert fails how to run an error. I've been searching on google for a few hours and the mongodb documentation and what I have tried I cannot operate.
The structure of the collection is:
{
"name" : String,
"providerId": Number,
"description": String,
"providers": [
{
"merchantId": String,
"name": String,
"valid": Boolean,
"data": String
},
{
"merchantId": String,
"name": String,
"valid": Boolean,
"data": String
},
{
"merchantId": String,
"name": String,
"valid": Boolean,
"data": String
}
]
}
Use this query to update existing data:
db.collection.update( { "providerId": ID, "providers": { $elemMatch: { "merchantId": MERCHANTID }}}, { $set: {
"providers.$.merchantId": MERCHANTID,
"providers.$.name": NAME,
"providers.$.valid": true,
"providers.$.data": DATA
}});
This working properly and correctly updated me the elements of the array. I want to when an element does not exist add it, without knowing if there are items or not, but not is if possible, probe to add upsert ( { upsert: true } ) parameter but gives me the following error. I think it is because it does not return any object search.
This is the error:
MongoError: The positional operator did not find the match needed from the query. Unexpanded update: providers.$.name
Is there any way to update the data in the subdocuments in the array and is compatible with add new ones if they don't exist? I've tried to search with the operator $in and it gives me error; also probe to search in different ways ( { "providers.merchantId": MERCHANTID } ) and others.
Thanks
There is an option to achieve what you want.
// step 1
var writeResult = db.collection.update({
"providerId" : ID,
"providers" : {
$elemMatch : {
"merchantId" : MERCHANTID
}
}
}, {
$set : {
"providers.$.merchantId" : MERCHANTID,
"providers.$.name" : NAME,
"providers.$.valid" : true,
"providers.$.data" : DATA
}
});
// step 2
if (!writeResult.nModified) { // if step 1 has succeeded on update, nModified == 1, else nModified == 0
db.collection.update({
"providerId" : ID,
"providers.merchantId" : {
$ne : MERCHANTID // this criteria is necessary to avoid concurrent issue
}
}, {
"$push" : {
"prividers" : {
"merchantId" : MERCHANTID,
"name" : NAME,
"valid" : true,
"data" : DATA
}
}
});
}

ExtJs root node

What is the root property value if I get a Json like that:
{
"status": {
"status": 0,
"msg": "Ok",
"protocolversion": "extjs.json"
},
"value": {
"table": [
[
"admin",
"Administrator",
""
],
[
"test",
"Test",
""
]
],
"total": 2
}
}
The data will be displayed in a gridpanel, 1 row is admin, 1 row is test, etc.
Tried:
value, value.table
How to get this to work?
value.table is correct for the root property, but you are using a json format that I don't think Ext is set up to handle by default. It has a reader for json that is used for an array of objects, not for an nested arrays of field values with no object mapping information.
If you have to use that format, you will either need to create your own readers/writers or just use Ext.Ajax.request(), and in the callback, parse the nested array into objects. Something like:
Ext.Ajax.request({
url: 'path.com/to/content',
success: function (response, operation) {
var data = Ext.JSON.decode(response.responseText);
var fields = data.value.table;
var records = [];
Ext.Array.each(fields, function (fieldArray, fieldIndex) {
Ext.Array.each(fieldArray, function(fieldValue, valueIndex) {
//Create record object if it doesn't exist
var record = records[valueIndex] || {};
//Create a switch statement based on the array index to set fields
switch(fieldIndex) {
case 0:
record.User_id = fieldValue;
break;
case 1:
record.Username = fieldValue;
break;
}
});
});
//Add the objects to the empty store
store.add(records);
}
});
That's not a production solution by any means since it doesn't handle that empty string at the end of your list or the case that you get a jagged array of arrays per field which I can't imagine what to do with. If it's within your control or influence, I would suggest using a format more like what Ext suggests so you can use the built in json proxy/reader/writer or go crazy with it and implement ext's remote procedure call format:
{
"success": true,
"message": "Success",
"data": [
{
"User_id": "admin",
"Username": "Administrator"
}, {
"User_id": "admin",
"Username": "Administrator"
}
]
}
In above example "value" is root property. But for JSON reader it's a property name (or a dot-separated list of property names if the root is nested).
so you can assign into your field you need following.
fields:['table.admin','table.test']

Resources