React Native: how can I achieve the dynamic keys with multiple objects - react-native

Here is my code I tried,
var array=[];
var list = this.state.list;
var getList = function(i){
var add = +i + 1;
return {
["value"+add]:{
Description:list[i].Description,
Length:list[i].Length,
Height:list[i].Height,
Weight:list[i].Weight,
VolumeWeight:list[i].VolumeWeight,
ActualWeight:list[i].ActualWeight,
}
}
}.bind(this)
for(var i in list){
array.push(getList(i));
}
var dataArray = array.map(function(e){
return JSON.stringify(e);
});
dataString = dataArray.join(",");
data1 = {
ConsigneeBranchName:this.state.searchText,
ConsigneeBranchCode:this.state.code,
ConsigneeBranchFullAddress:this.state.DAddress,
SenderBranchCode:this.state.code1,
SenderBranchName:this.state.searchTexts,
SenderBranchFullAddress:this.state.Address,
CreatedByEmployeeCode:id,
CreatedByEmployeeFullName:userName,
jsonString:{
JsonValues:{
id:"MyID",
values:dataString
}
}
}
But I want the result is exactly this
var result = {
"ConsigneeBranchName":"",
"ConsigneeBranchCode":"",
"ConsigneeBranchFullAddress":"",
"SenderBranchCode":"",
"SenderBranchName":"",
"SenderBranchFullAddress":"",
"CreatedByEmployeeCode":"",
"CreatedByEmployeeFullName":"",
"jsonString":"{
"JsonValues": {
"id": "MyID",
"values": {
"value1":{
"Description”:"testSmarter1",
"Length”:"60",
"Height”:"50",
"Weight”:"70",
"VolumeWeight”:"75",
"ActualWeight”:”78"
},
"value2:{
"Description":"Documents",
"Length":"120",
"Height":"68",
"Weight":"75",
"VolumeWeight":"122.4",
"ActualWeight":"123"
},
}
}
}
};
Please any one help me
I want the object with dynamic keys within a single object {key1:{des:1,value:as},key2:{des:2,value:aw},key3:{des:3,value:au}}
can you please help me I have tried so many times
see this below image I want this part, inside the single object, I can join multiple objects with dynamic keys

lodash already has a function called keyBy, you can use it to get this functionality. If adding lodash doesn't make sense in your project.
I have implemented a vanilla JS version.
function keyBy(array, mapperFn) {
const resultObj = {};
array.map(item => resultObj[mapperFn(item)] = item);
return resultObj;
}
function arrayToObject (array, keyName = 'id') {
return keyBy(array, function(element) {return element[keyName]});
}
API:
arrayToObject(targetArray, stringNameOfThePorpertyYouWantToUseAsKey);
USAGE:
const listOfUsers = [{name: 'Jenitha', reputation: 6}, {name: 'Chandan', reputation: 3}];
const mapOfUsersByName = arrayToObject(listOfUsers, 'name');

Related

QZ TRAY PRINITING ORDER NOT IN SEQ

I'm trying to print qz tray from javascript.
I have barcode with number in ascending order 1,2,3,4, 5 and so on.
I looping the seq correctly . but when printed out, it was not in order.
setTimeout("directPrint2()",1000);
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function directPrint2(){
var data;
var xhttp;
var v_carton = "' || x_str_carton ||'";
var carton_arr = v_carton.split('','');
var v1 = "' ||
replace(x_zebra_printer_id, '\', '|') ||
'".replace(/\|/g,"\\");
if(v1 == ""){
alert("Please setup ZPL Printer");
}
else{
xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
data = [ toNative(this.responseText) ];
printZPL(data, v1);
}
};
for (var j = 0; j < carton_arr.length; j++){
var url = "' || x_wms_url ||
'WWW_URL.direct_print_label?in_carton_no="+toValidStr(carton_arr[j]);
xhttp.open("GET", url, false);
xhttp.send();
sleep(5000);
}
}
};
',
'javascript'
What's missing from your example:
I do not see any looping logic in the example calling the printZPL function,
printZPL isn't a QZ Tray function and you're missing the code snippet which it calls. Usually this would be qz.print(config, data);.
Regardless of the missing information, the qz.print(...) API is ES6/Promise/A+ based meaning if you want to call qz.print multiple times in a row you need to use a Promise-compatible technique. (e.g. .then(...) syntax) between your print calls as explained in the Chaining Requests guide.
To avoid this, you can concatenate all ZPL data into one large data array. Be careful not to spool too much data at once.
If you know exactly how many jobs you'll be appending, you can hard-code the promise chain:
qz.websocket.connect()
.then(function() {
return qz.printers.find("zebra"); // Pass the printer name into the next Promise
})
.then(function(printer) {
var config = qz.configs.create(printer); // Create a default config for the found printer
var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ']; // Raw ZPL
return qz.print(config, data);
})
.catch(function(e) { console.error(e); });
Finally, if you do NOT know in advanced how many calls to qz.print(...) you can use a Promise loop as explained in the Promise Loop guide.
function promiseLoop() {
var data = [
"^XA\n^FO50,50^ADN,36,20^FDPRINT 1 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 2 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 3 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 4 ^FS\n^XZ\n"
];
var configs = [
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" }
];
var chain = [];
for(var i = 0; i < data.length; i++) {
(function(i_) {
//setup this chain link
var link = function() {
return qz.printers.find(configs[i_].printer).then(function(found) {
return qz.print(qz.configs.create(found), [data[i_]]);
});
};
chain.push(link);
})(i);
//closure ensures this promise's concept of `i` doesn't change
}
//can be .connect or `Promise.resolve()`, etc
var firstLink = new RSVP.Promise(function(r, e) { r(); });
var lastLink = null;
chain.reduce(function(sequence, link) {
lastLink = sequence.then(link);
return lastLink;
}, firstLink);
//this will be the very last link in the chain
lastLink.catch(function(err) {
console.error(err);
});
}
Note: The Promise Loop is no longer needed in QZ Tray 2.1. Instead, since 2.1, an array of config objects and data arrays can be provided instead.

Vue.js list not updating when data changes

i'm trying re-organised a list of data. I have given each li a unique key, but still, no luck!
I have had this working before exactly like below, think i'm cracking up!
let app = new Vue({
el: '#app',
data: {
list: [
{ value: 'item 1', id: '43234r' },
{ value: 'item 2', id: '32rsdf' },
{ value: 'item 3', id: 'fdsfsdf' },
{ value: 'item 4', id: 'sdfg543' }
]
},
methods: {
randomise: function() {
let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
this.list = input;
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in list" :key="item.id">{{ item.value }}</li>
</ul>
Randomize
</div>
Edit:
Thanks for the answers, to be honest the example I provided may not have been the best for my actual issue I was trying to solve. I think I may have found the cause of my issue.
I'm basically using a similar logic as above, except i'm moving an array of objects around based on drag and drop, this works fine with normal HTML.
However, i'm using my drag and drop component somewhere else, which contains ANOTHER component and this is where things seem to fall apart...
Would having a component within another component stop Vue from re-rendering when an item is moved within it's data?
Below is my DraggableBase component, which I extend from:
<script>
export default {
data: function() {
return {
dragStartClass: 'drag-start',
dragEnterClass: 'drag-enter',
activeIndex: null
}
},
methods: {
setClass: function(dragStatus) {
switch (dragStatus) {
case 0:
return null;
case 1:
return this.dragStartClass;
case 2:
return this.dragEnterClass;
case 3:
return this.dragStartClass + ' ' + this.dragEnterClass;
}
},
onDragStart: function(event, index) {
event.stopPropagation();
this.activeIndex = index;
this.data.data[index].dragCurrent = true;
this.data.data[index].dragStatus = 3;
},
onDragLeave: function(event, index) {
this.data.data[index].counter--;
if (this.data.data[index].counter !== 0) return;
if (this.data.data[index].dragStatus === 3) {
this.data.data[index].dragStatus = 1;
return;
}
this.data.data[index].dragStatus = 0;
},
onDragEnter: function(event, index) {
this.data.data[index].counter++;
if (this.data.data[index].dragCurrent) {
this.data.data[index].dragStatus = 3;
return;
}
this.data.data[index].dragStatus = 2;
},
onDragOver: function(event, index) {
if (event.preventDefault) {
event.preventDefault();
}
event.dataTransfer.dropEffect = 'move';
return false;
},
onDragEnd: function(event, index) {
this.data.data[index].dragStatus = 0;
this.data.data[index].dragCurrent = false;
},
onDrop: function(event, index) {
if (event.stopPropagation) {
event.stopPropagation();
}
if (this.activeIndex !== index) {
this.data.data = this.array_move(this.data.data, this.activeIndex, index);
}
for (let index in this.data.data) {
if (!this.data.data.hasOwnProperty(index)) continue;
this.data.data[index].dragStatus = 0;
this.data.data[index].counter = 0;
this.data.data[index].dragCurrent = false;
}
return false;
},
array_move: function(arr, old_index, new_index) {
if (new_index >= arr.length) {
let k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing
}
}
}
</script>
Edit 2
Figured it out! Using the loop index worked fine before, however this doesn't appear to be the case this time!
I changed the v-bind:key to use the database ID and this solved the issue!
There are some Caveats with arrays
Due to limitations in JavaScript, Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
When you modify the length of the array, e.g. vm.items.length = newLength
To overcome caveat 1, both of the following will accomplish the same as vm.items[indexOfItem] = newValue, but will also trigger state updates in the reactivity system:
Vue.set(vm.items, indexOfItem, newValue)
Or in your case
randomise: function() {
let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
Vue.set(input, randomIndex, input[i]);
Vue.set(input, i, itemAtIndex);
}
this.list = input;
}
Here is an working example: Randomize items fiddle
Basically I changed the logic of your randomize function to this:
randomize() {
let new_list = []
const old_list = [...this.list] //we don't need to copy, but just to be sure for any future update
while (new_list.length < 4) {
const new_item = old_list[this.get_random_number()]
const exists = new_list.findIndex(item => item.id === new_item.id)
if (!~exists) { //if the new item does not exists in the new randomize list add it
new_list.push(new_item)
}
}
this.list = new_list //update the old list with the new one
},
get_random_number() { //returns a random number from 0 to 3
return Math.floor(Math.random() * 4)
}
randomise: function() { let input = this.list;
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = this.list[randomIndex];
Vue.set(this.list,randomIndex,this.list[i])
this.list[randomIndex] = this.list[i];
this.list[i] = itemAtIndex;
} this.list = input;
}
Array change detection is a bit tricky in Vue. Most of the in place
array methods are working as expected (i.e. doing a splice in your
$data.names array would work), but assigining values directly (i.e.
$data.names[0] = 'Joe') would not update the reactively rendered
components. Depending on how you process the server side results you
might need to think about these options described in the in vue
documentation: Array Change Detection.
Some ideas to explore:
using the v-bind:key="some_id" to have better using the push to add
new elements using Vue.set(example1.items, indexOfItem, newValue)
(also mentioned by Artokun)
Source
Note that it works but im busy so i cant optimize it, but its a little bit too complicted, i Edit it further tomorrow.
Since Vue.js has some caveats detecting array modification as other answers to this question highlight, you can just make a shallow copy of array before randomazing it:
randomise: function() {
// make shallow copy
let input = this.list.map(function(item) {
return item;
});
for (let i = input.length-1; i >=0; i--) {
let randomIndex = Math.floor(Math.random()*(i+1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
this.list = input;
}

using vue.set in vuex is not updating the state

I'm trying to add an object into a nested array, and it is not working, but I've used this for other states and it works fine.
Has it got something to do with it begin a nested array?
this is the code I'm using
Vue.set(state.sections[getCurrentSection(state).index].rows[getCurrentRow(state).index].columns[getCurrentColumn(state).index].elements, 0, element)
this is the element object
var element = {
id: id,
style: {
backgroundColor: {
value: 'rgba(255,255,255,1)',
},
},
}
what am I doing wrong?
UPDATE
Another option to clone:
function hasProp(arg1, arg2) {
return Object.prototype.hasOwnProperty.call(arg1, arg2);
}
function extend(arg1, arg2) {
const keys = Object.keys(arg2);
const len = keys.length;
let i = 0;
while (i < len) {
arg1[keys[i]] = arg2[keys[i]];
i += 1;
}
if (hasProp(arg2, 'toString')) {
arg1.toString = arg2.toString;
}
if (hasProp(arg2, 'valueOf')) {
arg1.valueOf = arg2.valueOf;
}
return arg1;
}
const obj1 = {
a: 1,
b: 2,
c: { a: 1, b: 2}
};
const cloned = extend({}, obj1);
cloned.a = 9999;
console.log(obj1, cloned);
Make a deep copy of your state.sections;
Create a new object and make your modifications on it;
Replace state.sections with you new object - state.sections = Object.assign({}, newObject).
Your state and your view updated.

Custom data source with WinJS?

I am currently implementing a custom data source in a Windows8 application. However, I got some trouble with it: no data is displayed.
First, here is the code:
var dataArray = [
{ title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" },
// Other data taken from Windows8 ListView quick start
{ title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" }
];
var searchAdDataAdapter = WinJS.Class.define(
function () {}, // Constructor
{
itemsFromIndex: function (requestIndex, countBefore, countAfter) {
var that = this;
if (requestIndex >= that._maxCount) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(UI.FetchError.doesNotExist));
}
var fetchSize, fetchIndex;
// See which side of the requestIndex is the overlap.
if (countBefore > countAfter) {
// Limit the overlap
countAfter = Math.min(countAfter, 10);
// Bound the request size based on the minimum and maximum sizes.
var fetchBefore = Math.max(
Math.min(countBefore, that._maxPageSize - (countAfter + 1)),
that._minPageSize - (countAfter + 1)
);
fetchSize = fetchBefore + countAfter + 1;
fetchIndex = requestIndex - fetchBefore;
} else {
countBefore = Math.min(countBefore, 10);
var fetchAfter = Math.max(Math.min(countAfter, that._maxPageSize - (countBefore + 1)), that._minPageSize - (countBefore + 1));
fetchSize = countBefore + fetchAfter + 1;
fetchIndex = requestIndex - countBefore;
}
// Create an array of IItem objects:
// results =[{ key: key1, data : { field1: value, field2: value, ... }}, { key: key2, data : {...}}, ...];
for (var i = 0, itemsLength = dataArray.length ; i < itemsLength ; i++) {
var dataItem = dataArray[i];
results.push({
key: (fetchIndex + i).toString(),
data: dataArray[i]
});
}
// Get the count.
count = dataArray.length;
return {
items: results, // The array of items.
offset: requestIndex - fetchIndex, // The index of the requested item in the items array.
totalCount: count
};
},
getCount: function () {
return dataArray.length;
}
}
);
var searchAdDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function () {
this._baseDataSourceConstructor(new searchAdDataAdapter());
});
// Create a namespace to make the data publicly
// accessible.
var publicMembers = {
itemList: new searchAdDataSource()
};
WinJS.Namespace.define("DataExample", publicMembers);
I know the code is a little bit long, but the major part of it is taken from official Microsoft custom data source quick start.
I tried to debug it, but it seems the code contained in itemFromIndex is never used (my breakpoint is never reached).
The HTML code is:
<div id="basicListView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : DataExample.itemList.dataSource}">
</div>
I do not use any template for the moment, to simplify the code as more as I can. Data are normally displayed in text this way (but nothing appears).
Have one of this great community any idea?
Furthermore, I do not understand the countBefore and countAfter parameters, even with the documentation. Can somebody explain it to me with other words?
Thanks a lot! :)
Try modifying your HTML code to the following:
<div id="basicListView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : DataExample.itemList}">
</div>
No need to call the .datasource member, as you are talking to the datasource directly.

dojo ItemFileReadStore.getValue mixed return value is not handled as string

I'am using dojo.data.ItemFileReadStore to query a json file with data. the main purpose is finding translations at Js level.
The Json data has "id" the word and "t" the translation
function translate(word)
{
var json = '/my/language/path/es.json';
var reader = new dojo.data.ItemFileReadStore({
url: json
});
var queryObj = {};
queryObj["id"] = word;
reader.fetch({
query: queryObj,
onComplete: function(items, request){
if (items.length > 0) {
var t = reader.getValue(items[0], 't');
if (dojo.isString(t)) {
return t;
}
}
return word;
},
onError: function(error, request){
return word;
}
});
}
The return value is always a undefined wether there is a translation or not. any ideas?
I tried typecasting with no success.
You can do it like this:
function translate(wordId) {
var translatedWord= wordId;
var store = new dojo.data.ItemFileReadStore({ data: storeData });
store.fetch({ query: { id: wordId },
onItem: function (item) {
translatedWord= (store.getValue(item, 't'));
}
});
return translatedWord;
}