How to change the currentText of repeated ComboBox in QML? - javascript

As I understand it, it is not possible to directly change the property currentText of a QML ComboBox. Instead, one needs to access it via currentIndex. However, I cannot seem to get it either. The JS code I need to update the text of a ComboBox with is the following:
function fillCombosFromHistory (s, rep1, rep2, replength) {
let u = s.replace(/\s+/g,'').split('&');
let v = [];
for (let i = 0; i < u.length; i++) {
v.push({
key: u[i].split('=')[0],
value: u[i].split('=')[1]
})
}
for (let j = 0; j < v.length; j++) {
for (let k = 0; k < replength; k++) {
if (v[j].key === rep1.itemAt(k).text) {
rep2.itemAt(k).model.currentIndex.text = v[j].value;
}
}
}
}
Here I pass the ids of two repeaters rep1 and rep2, where rep1 repeats Text (as a label) and rep2 repeats ComboBox. They are forcefully of the same length, so only one replength.
PS. I currently get the error TypeError: Value is undefined and could not be converted to an object.

So, I solved the problem. Apparently I was just confused about the properties of ComboBox. I changed the line
rep2.itemAt(k).model.currentIndex.text = v[j].value;
to
rep2.itemAt(k).editText = v[j].value;
and then some logic in other functions to accomodate the change and now everything works. Thanks anyway for the helpful hints!

Related

Correct way of displaying nested array object - issue with sorting an array

I have got set of Web API 2.2 fetched data. It is stored in an Angular array of type object. That object has declared field for storing another array.
Simply, main object is of type Client, it has properties like name, surname, but also has a collection of contracts which are assigned to that client.
That's the class .ts:
export interface Client {
Id: number;
name: string;
surname: string;
Contracts: any;
}
I managed to display all the data in tables, get one user from table, but what I am struggling with is to sort this array of clients in the following way:
If I select/type - whatever - some contract property (lets say ContractId) I want to receive only Clients whose got at lest one contract with the ContractID.
Alright, but what doesn't seem to be intuitive for me is the following.
I access my clients array, declared as clients: Array<Client> = [];
Output in the console is clear, I see object, and all it's fields including contracts.
But when I try to access this.clients[i] (in a loop of course) or even this.clients[0].Contracts, I get undefined.
So far I've tried changing Contracts to ['Contracts'], or adding [0] before, but nothing seems to work.
Following code:
for (var i = 0; i < this.clients.length; i++) {
console.log(this.clients[i]);
console.log(this.clients[i].Contracts);
for (var j = 0; j < this.clients[i].Contracts.length; j++) {
console.log(this.clients[i].Contracts[j]);
}
}
generates output (undefined error):
in output log, you have contracts field, not Contracts (small c)
Change Code Segment
for (var i = 0; i < this.clients.length; i++) {
console.log(this.clients[i]);
console.log(this.clients[i].Contracts);
for (var j = 0; j < this.clients[i].Contracts.length; j++) {
console.log(this.clients[i].Contracts[j]);
}
}
To
for (var i = 0; i < this.clients.length; i++) {
console.log(this.clients[i]);
console.log(this.clients[i].Contracts);
for (var j = 0; j < this.clients[i].contracts.length; j++) {
console.log(this.clients[i].contracts[j]);
}
}
it will be better u can use for-each loop
for (let client of this.clients) {
console.log(clients);
console.log(client.contracts);
for (let contact of client.contracts) {
console.log(contact);
}
}
Hope this will helps ..!!

value of particular field not updating in for loop

I have two for loops,the value inside inner for loop is not updating with the value of outer for loop.
I have 2 arrays,
let getExhibitors= [{"_id":"5c78102829c1cc00082c9956","title":"Accenture","sponsorSortOrder":1,"sortOrder":1,"__v":1,"beconDetails":[],"productDemos":[],"sponsorTags":[],"exhibitorTags":[],"eventId": "5c78088a29c1cc00082c990b","entityId": "5c78102829c1cc00082c9956","favourite":true,"notes":'hey it is exhibitor'}]
let exhibitorsArray= [{"_id":"5d7797029f3ae4000821d2df","favourite":true,"entityId":"5c78109529c1cc00082c9959","module Id":"EXHIBITORS_MODULE","eventId":"5c78088a29c1cc00082c990b","__v":0,"modifiedDate":"2019-09-10T12:34:48.993Z","creationDate":"2019-09-10T12:28:50.526Z","comments":"","notes":"",},{"_id":"5d5cf3d8adaac20007cbcc12","favourite":false,"entityId":"5c78102829c1cc00082c9956","moduleId":"EXHIBITORS_MODULE","eventId":"5c78088a29c1cc00082c990b","__v":0,"modifiedDate":"2019-09-17T10:04:03.891Z","creationDate":"2019-08-21T07:33:44.077Z","comments":"","notes":"hey it is exhibitor","id":"5d5cf3d8adaac20007cbcc12"}]
for(let i=0;i<exhibitorsArray.length;i++){
console.log("inside first forloop ",exhibitorsArray[i]);
for(let j=0;j<getExhibitors.length;j++){
console.log("inside second forloop",getExhibitors[j]);
if((exhibitorsArray[i].entityId==getExhibitors[j].entityId ) && (exhibitorsArray[i].eventId==getExhibitors[j].eventId)){
console.log("exhibitor present",getExhibitors[j],exhibitorsArray[i]);
getExhibitors[j].favourite=exhibitorsArray[i].favourite
getExhibitors[j].notes=exhibitorsArray[i].notes
console.log("exhibitors final",getExhibitors);
}
}
}
here value of exhibitorsArray[i].favourite is not assigning to getExhibitors[j].favourite and value of exhibitorsArray[i].notes is not assigning to getExhibitors[j].notes,I mean ,value inside the console "exhibitors final" is retaining the same,not updating.
Please help me out to solve it.
One of the keys you are using is wrong (entityId is _id).
You didn't provide loadedSynchData so I cannot properly test my code.
Please try the following:
for (let i = 0; i < exhibitorsArray.length; i++) {
for (let j = 0; j < getExhibitors.length; j++) {
if ((exhibitorsArray[i].entityId == getExhibitors[j]._id) && (loadedSynchData[i].eventId == getExhibitors[j].eventId)) {
console.log("exhibitor present", getExhibitors[j], exhibitorsArray[i]);
getExhibitors[j].favourite = exhibitorsArray[i].favourite
getExhibitors[j].notes = exhibitorsArray[i].notes
}
}
}
This is why assignment operation failed.
Both getExhibitors[j].entityId and getExhibitors[j].eventId do not exist at all. You should also check if this,loadedSynchData[i].eventId really exists since the data for this array loadedSynchData is not provided yet.

Javsacript for loop giving out weird results

I wrote a simple for loop to perform some DOM manipulation based on the json response. Here's the code I have
onSuccess: function(a) {
var b = a.items.length;
for (i = 0; i < b; i++)
user_id = a.items[i].id;
$('#user_id').checked = true;
selectUserSettings(user_id);
}
},
In one example I was working with, the resultset 'a' had 14 items in them. The for loop, when adding a breakpoint, shows the value of i at 0,1,2,2,3,2,3,4,2,3,4,5... Basically it resets and begins at 2 and goes upto 1 additional index before doing it over again... What am I doing wrong here ?Any help would be greatly appreciated.
Most probably because of this line for (i = 0; i < b; i++) when i is declared without a let or var keyword , it is in global scope.
Change this to
for (let i = 0; i < b; i++)
Also if my understanding is correct you want to use user_id variable to access the element. If it is so then change
user_id = a.items[i].id;
$('#user_id').checked = true;
to
let user_id = a.items[i].id;
$('#'+user_id).checked = true;

JavaScript addEventListener() not working as expected

I have never used addEventListener(), but I cannot write the HTML equivalent I would like for each <div> I am treating as a button because of the way I am generating content. The equivalent would be:
<div onmousedown="jsItems[someId].toggleImage(someGallery, someIndex);"></div>
What I've been trying is this:
JsTree.prototype.addGalleries = function(inElements) {
// ...unrelated code here removed for StackOverflow...
for (var i = 0; i < this.jsGalleries.length; i++) {
for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) {
var self = this;
this.jsGalleries[i].buttons[j].addEventListener("mousedown", function() {
self.toggleImage(i, j);
});
}
}
}
Where i counts from 0 to 1 and j counts from 0 to 2 (for both i in this case), i represents someGallery, j represents someIndex, and I could access someId with this.id inside the code above (or with self.id inside addEventListener's function).
The problem is that although clicking on one of these "buttons" (<div>s) does trigger:
JsTree.prototype.toggleImage = function(inGallery, inIndex) {
alert(this.id+", "+inGallery+", "+inIndex);
}
that it always alerts "8, 2, 3" regardless of which button is clicked. The "8" is correct but I have no idea why "2" or "3" are alerted. They seem to just be 1 more than what i and j count to (verified by trying j < this.jsGalleries[i].buttons.length-1 which alerts "8, 2, 2").
Edit: someId, someGallery, and someIndex are not real variables, they are junk I made up to try to explain the problem.
This is a classic JS mistake. The problem is that the values of i and j are not captured in any function scope, and your event handlers are asynchronous. That means that when your event handler runs, both for loops have run to completion, thus i == this.jsGalleries.length and j === this.jsGalleries[this.jsGalleries.length - 1].buttons.length.
Try out one of these:
JsTree.prototype.addGalleries = function(inElements) {
// ...unrelated code here removed for StackOverflow...
for (var i = 0; i < this.jsGalleries.length; i++) {
for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) {
(function(self, innerI, innerJ){
var galleryEl = self.jsGalleries[innerI].buttons[innerJ];
galleryEl.addEventListener("mousedown", function() {
self.toggleImage(innerI, innerJ);
});
})(this, i, j);
}
}
}
Or possibly clearer:
JsTree.prototype.addGalleries = function(inElements) {
// ...unrelated code here removed for StackOverflow...
var addHandler = function(self, i, j){
self.jsGalleries[i].buttons[j].addEventListener("mousedown", function() {
self.toggleImage(i, j);
});
};
for (var i = 0; i < this.jsGalleries.length; i++) {
for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) {
addHandler(this, i, j);
}
}
}
It's not a problem with addEventListener. This is a common mistake. In order to understand what's going on, I have to explain how closures work.
When you have a loop and a function inside of it:
var i = 5;
while(i--){
setTimeout(function(){
console.log(i);
}, 100);
}
Each function is given a reference to the variable i. That means that they don't retain the value of i at the time you defined them. Again, I'll restate, each function has a reference to the same variable i, not to the value that it had at the time the function was declared. In my example above, all of the setTimeout's are defined asynchronously. The anonymous functions all fire at 100 milliseconds and each one logs the value that's in i at the time that the function was run. In my example, that value would be -1 for all the functions.
There are 2 ways to solve this. I'll show you the easy one first:
for (var i = 0; i < this.jsGalleries.length; i++) {
for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) {
var self = this;
self.gallery = {i: i, j: j};
this.jsGalleries[i].buttons[j].addEventListener("mousedown", function() {
self.toggleImage(self.gallery.i, self.gallery.j);
});
}
}
Here, you're storing the values on the actual DOM element. These values are equivalent to the values at the time that the loop was run, so the event listener grabs the correct value. Notice I nested the value in an object called gallery. I did this to kind of namespace it. It's not a good idea to store values on elements in the DOM, just in case browsers end up implementing a property with the same name. I feel like gallery is safe enough.
The other option, and probably the best practice, for fixing this is to use closures to your advantage.
for (var i = 0; i < this.jsGalleries.length; i++) {
for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) {
var self = this;
this.jsGalleries[i].buttons[j].addEventListener("mousedown", (function closure(self, i, j){
return function actualListener(){
self.toggleImage(i, j);
}
})(self, i, j));
}
}
In this case, we create a self executing function (called closure in my example) which runs immediately when we're creating the listener. Let me state it again, this function runs the moment the listener is being added, NOT when it's run. The reason we do this is so we can pass in the values we want to save for later, in this case, self, i, and j. Then, when the event occurs, the function that ACTUALLY gets run is the inner function (called actualListener). actualListener has a copy of all the values stored in its closure at the time that the closure function was run.

Calling a javascript array without knowing naming conventions in advance

I am calling an ajax function that returns a dataset (response) with data column labels. One of the column labels changes depending on where the call was initiated from.
Normally the following code accesses the response variable if the column label is hard coded:
for (var i = 0; i < response.d.length; i++) {
data.setValue(i, 1, response.d[i].Emissions);
}
However, I need to be able to access the response variable using a separate string variable that is passed in since the label changes. Below is my feeble attempt at doing it, but it isn't working. What is the correct syntax for doing that?
var columnLabel = 'Emissions';
for (var i = 0; i < response.d.length; i++) {
data.setValue(i, 1, response.d[i].columnLabel);
}
You need to use the []-operator:
data.setValue(i, 1, response.d[i][columnLabel]);
obj.property is equivalent to obj['property'].
Try this:
for (var i = 0; i < response.d.length; i++) {
data.setValue(i, 1, response.d[i]['Emissions']);
}

Categories