Ok, I have model with one property(provider) as object. It can change at all.
There is example, where I change provider. There can be any parametrs, image can has dpi, json can has another parametr.
So, when I select anoter provider, how to merge model property(provider) and updated provider?
this.providerWasChange = function() {
// here I should update model with provider parametrs(update full object)
$scope.provider
}
https://jsfiddle.net/77z165uj/11/
Hm,
var model = {
id: '1',
name: '',
childModels: [{
id: '1.1',
name: 'item1',
provider: {
name: 'imageProvider'
options: {
transparent: false,
dpi: 96
}
}
}, {
id: '1.2',
name: 'item2'
provider: {
name: 'jsonProvider'
options: {
uppercase: true,
}
}
}]
}
$scope.providers = [{
name: 'jsonProvider',
displayNmae: "jsonProvider",
options:{
uppercase:$scope.providerOptions,
}
}, {
name: 'imageProvider',
displayNmae: "imageProvider",
options:{
transparent:$scope.transparent,
dpi::$scope.dpi
}
}];
_changeProvider = function(data) {
if (data !== null) {
for (var i = 0; i < $scope.providers.length; i++) {
if ($scope.providers[i].name === data.name) {
$scope.providers[i].options = data.options
return $scope.providers[i];
}
};
}
}
I'm looking for a fuction or angular method, that set chosen provider blank with setted options from model back. For example, I'd like to change provider of item 2 to image provider(old values(if there is coincidence) should rewrites to model(item2), other should be deleted, and new - setted)
Related
let object=
[
{
id:`01`,
name:`fish`,
type:null,
care:'owner',
},
{
id:`02`,
name:`fish`,
type:'fresh',
care:'peter',
},
{
id:`03`,
name:`fish`,
type:`fresh`,
care:'amy',
},
{
id:`04`,
name:`fish`,
type:`tank`,
care:'abc',
},
{
id:`05`,
name:`animal`,
type:`pet`,
care:'teen',
},,
{
id:`06`,
name:`animal`,
type:`pet`,
care:'ran',
},
{
id:`07`,
name:`animal`,
type:null,
care:'roh',
},
{
id:`08`,
name:`food`,
type:`veg`,
care:'test',
},
{
id:`09`,
name:`food`,
type:null,
care:'dop',
}
]
object.map((value)=>{
console.log(value.name)
// i am calling function here by passing value.name as a parameter
let gotValue = functionName(value.name);
// using type also
if(typeof value.type!=="string"){
// Do some task here with gotValue
}
})
I have this object and i am getting some value from it for ex getting name from it as i want to pass this name to function but the problem is due to repeat of data the function calling again and again is there any possibility i can run function inside map but with unique value any help ?
as my output is getting like this
fish
fish
fish
animal
animal
animal
and this value.name is passing inside my function so its repeating like this
functionName(fish);
functionName(fish);
functionName(fish);
functionName(animal);
functionName(animal);
functionName(animal);
multiple time function is running with same name and getting duplicate values
just need my function run with unique name
functionName(fish)
functionName(animal);
functionName(food);
as i want to stay inside map function because i am performing some task which can only be possible inside map that's why i need unique value
You can use Set which can be used to test if the object with value already exists or not. It will only call the function only once.
let object = [
{
id: `01`,
name: `fish`,
type: null,
},
{
id: `02`,
name: `fish`,
type: `fresh`,
},
{
id: `03`,
name: `fish`,
type: `tank`,
},
{
id: `04`,
name: `animal`,
type: `pet`,
},
{
id: `05`,
name: `animal`,
type: `wild`,
},
{
id: `06`,
name: `animal`,
type: null,
},
{
id: `07`,
name: `food`,
type: `veg`,
},
{
id: `08`,
name: `food`,
type: null,
},
];
const dict = new Set();
object.map((value) => {
if (!dict.has(value.name)) { // Run only if objet with name is not already existed in dict
dict.add(value.name);
console.log(value.name); // For testing
// functionName(value.name);
}
});
If you want to call the function with two filters then you can use some to find the elements in an array. See I've now declared dict as an array
let object = [{
id: `01`,
name: `fish`,
type: null,
},
{
id: `02`,
name: `fish`,
type: `fresh`,
},
{
id: `03`,
name: `fish`,
type: `tank`,
},
{
id: `04`,
name: `animal`,
type: `pet`,
},
{
id: `05`,
name: `animal`,
type: `wild`,
},
{
id: `06`,
name: `animal`,
type: null,
},
{
id: `07`,
name: `food`,
type: `veg`,
},
{
id: `08`,
name: `food`,
type: null,
},
{
id: `09`,
name: `food`,
type: null,
},
{
id: `10`,
name: `fish`,
type: `tank`,
},
];
const dict = [];
object.map((value) => {
const { name, type } = value;
if (!dict.some((obj) => obj.name === name && obj.type === type)) {
// Run only if objet with name is not already existed in dict
dict.push({ name, type });
console.log(name, type); // For testing
// functionName(value.name);
}
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm working on an vue-application where I have a component for driving licenses.
I have the following:
data() {
return {
custom_licenses: [],
basic_licenses: []
}
}
within my methods, I have this:
regular_licenses() {
this.$store.dispatch("license/read").then(response => {
response.licenses.map((license, key) => {
// PUSH LICENSES WITH TYPE 'BASIC' TO this.basic_licenses
// PUSH LICENSES WITH TYPE 'CUSTOM' TO this.custom_licenses
});
});
},
and in my created() i have this:
created() {
this.regular_licenses()
}
The response from my dispatch, returns this:
licenses:
[
{
id: 1,
type: 'basic',
name: 'AMa'
},
{
id: 2,
type: 'basic',
name: 'A2'
},
{
id: 3,
type: 'basic',
name: 'C'
},
{
id: 4,
type: 'custom',
name: 'C1'
},
{
id: 5,
type: 'custom',
name: 'D'
},
and so on...
]
Now I want to loop through the array and separate or push them into custom_licenses and basic_licenses based on the type-attribute - how can I achieve that?
Try this
regular_licenses() {
this.$store.dispatch("license/read").then(response => {
response.licenses.map((license, key) => {
switch (license.type)
case 'basic':
this.basic_licenses.push({ ...license });
break;
case 'custom':
this.custom_licenses.push({ ...license });
break;
});
});
},
Update your Code Block:
response.licenses.map((license, key) => {
// PUSH LICENSES WITH TYPE 'BASIC' TO this.basic_licenses
if(license['type'] == 'basic') {
//deep clone
let tmpLicense = JSON.parse(JSON.stringify(license));
basic_licenses.push(tmpLicense);
} else if(license['type'] == 'custom') {
// PUSH LICENSES WITH TYPE 'CUSTOM' TO this.custom_licenses
//deep clone
let tmpLicense = JSON.parse(JSON.stringify(license));
custom_licenses.push(tmpLicense);
}
});
I've copied the Grid Component Example into a single-file component (Grid.vue). Within that component, I'm not able to access the columns prop. console.log(this.columns) always prints: [__ob__: Observer] to the log. Can someone tell me why? This works fine in their example on the page and in JSFiddle.
Here's my Grid.vue file:
<script>
export default {
name: 'grid',
props: {
data: Array,
columns: Array,
filterKey: String
},
data: function() {
var sortOrders = {}
console.log(this.columns)
this.columns.forEach((column) => {
sortOrders[column] = 1
});
return {
sortCol: '',
sortOrders: sortOrders
}
},
computed: {
filteredData: function () {
var sortCol = this.sortCol
var filterKey = this.filterKey && this.filterKey.toLowerCase()
var order = this.sortOrders[sortCol] || 1
var data = this.data
if (filterKey) {
data = data.filter((row) => {
return Object.keys(row).some((key) => {
return String(row[key]).toLowerCase().indexOf(filterKey) > -1
})
})
}
if (sortCol) {
data = data.slice().sort((a, b) => {
a = a[sortCol]
b = b[sortCol]
return (a === b ? 0 : a > b ? 1 : -1) * order
})
}
return data
}
},
filters: {
capitalize: function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
},
methods: {
sortBy: function (key) {
this.sortCol = key
console.log(this.sortOrders[key])
this.sortOrders[key] = this.sortOrders[key] * -1
console.log(this.sortOrders[key])
}
},
created() {
},
mounted() {
// var app = this
},
}
</script>
I'm using this component within another component like so:
<template>
<div>
<form id="search">
Search <input name="query" v-model="searchQuery">
</form>
<grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid>
</div>
</template>
<script>
import Grid from './Grid.vue';
export default {
name: 'things-grid',
data: function() {
return {
things: [],
thingColumns: [],
searchQuery: ''
}
},
mounted() {
var app = this
app.things = [
{id: 1, this: 'this 1', that: 'that 1', thing: 'thing 1'},
{id: 2, this: 'this 2', that: 'that 2', thing: 'thing 2'},
{id: 3, this: 'this 3', that: 'that 3', thing: 'thing 3'},
{id: 4, this: 'this 4', that: 'that 4', thing: 'thing 4'},
{id: 5, this: 'this 5', that: 'that 5', thing: 'thing 5'},
]
app.thingColumns = [
'this', 'that', 'thing'
]
app.searchQuery = ''
},
components: { Grid }
}
</script>
In:
<grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid>
The value of this.thingColumns is passed as :columns when mounting.
Thus, the console.log(this.columns) inside Grid.vue/data() prints when it is mounting.
And when it is mounting, thingColumns is empty in the parent:
data: function() {
return {
things: [],
thingColumns: [], // initially empty
searchQuery: ''
}
},
mounted() {
var app = this
// ...
app.thingColumns = [ // this code only runs after it is mounted
'this', 'that', 'thing'
]
// ...
},
Since the console.log(this.columns) inside Grid.vue/data() prints when it is mounting, that is, before it is mounted, it prints an empty array:
[__ob__: Observer] // this is an empty array, the __ob__ thing is related to Vue internals
Because, well, parent's thingColumns will only have data after the mounted() hook executes.
And since it is a reactive array, when you update it, it will update the child grid component as well.
Solution:
Move the property initalization code from mounted() to created():
created() { // was mounted()
var app = this
// ...
app.thingColumns = [
'this', 'that', 'thing'
]
// ...
},
This will initialize the data sooner and make it available in time for the console.log() in the child to pick it up.
This is the first version of the code that I have attempted. I've tried a whole lot of other things like mutual exclusion, adding catch blocks everywhere, and Promise anti-patterns, but I can't seem to get over this mental or syntactical block:
populateJoins() {
let promises = [];
for (let c in this.columns) {
let transformColumn = this.columns[c];
if (transformColumn.joins) {
let joinPointer = this.databaseObject;
for (let j in transformColumn.joins) {
let join = transformColumn.joins[j];
if (joinPointer[join.as] != null) {
joinPointer = joinPointer.dataValues[join.as];
} else {
if (this.requestQuery[toCamelCase(join.as) + 'Id']) {
promises.push(
join.model.findOne({where: {id: this.requestQuery[toCamelCase(join.as) + 'Id']}})
.then((tmp) => {
joinPointer.dataValues[join.as] = tmp;
}));
} else if (joinPointer[toSnakeCase(join.as) + '_id']) {
promises.push(
join.model.findOne({where: {id: joinPointer[toSnakeCase(join.as) + '_id']}})
.then((tmp) => {
joinPointer.dataValues[join.as] = tmp;
}));
}
}
}
}
}
return Promises.all(promises);
}
And this is the structure of this.columns:
child1Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child1'),
as: 'Child1'
}],
hidden: true
},
child2Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child2'),
as: 'Child2'
}],
hidden: true
},
child1Status1Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child1'),
as: 'Child1'
},{
model: Database.getInstance().getModel('status1'),
as: 'Status1'
}],
hidden: true
},
child1Status2Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child1'),
as: 'Child1'
},{
model: Database.getInstance().getModel('status2'),
as: 'Grandchild2'
}],
hidden: true
},
serverName: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child1'),
as: 'Child2'
},{
model: Database.getInstance().getModel('grandchild'),
as: 'Grandchild'
},{
model: Database.getInstance().getModel('great_grandchild'),
as: 'GreatGrandchild'
}],
hidden: true
},
child2Status1Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child2'),
as: 'Child2'
},{
model: Database.getInstance().getModel('status1'),
as: 'Grandchild1'
}],
hidden: true
},
child2Status2Name: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child2'),
as: 'Child2'
},{
model: Database.getInstance().getModel('status2'),
as: 'Grandchild2'
}],
hidden: true
},
archetypeName: {
name: 'name',
forceSelect: true,
joins: [{
model: Database.getInstance().getModel('child2'),
as: 'Child2'
},{
model: Database.getInstance().getModel('archetype'),
as: 'Archetype'
},{
model: Database.getInstance().getModel('archetype'),
as: 'ArchetypeLink'
}],
hidden: true
},
So for things I've already learned, joinPointer[join.as] != null will never prevent duplicate Child database calls from firing because the property will not be populated until the promises finish resolving.
Similarly, none of the grandchildren will populate because they have to wait for the children to populate, and if the grandchildren fulfill first, then they will never make it into the child object. The same goes for great-grandchildren.
I read this answer, where he says, "If you already have them in an array then they are already executing." I understand that the contents of the Promise will already resolve, which is why in other code I always use numerical indices to populate objects, i.e. jsonObject['list'][i]['anotherList'][j] = ...;, but I don't see how I can do this here.
I've been working on this for a while and haven't come up with a solution, so any workable code is more than appreciated.
The code in the question is difficult to follow but it appears that what you are trying to do is reasonably simple, ie execute a set of asynchronous findOne queries in series and progressively construct an ever-deeper hierarchy comprising the returned results.
If so, then :
you can use a reduce() pattern, see "The Collection Kerfuffle" here.
the full .columns object is unnecessary - you just need .columns.greatGrandchildName.joins.
The code should look at least something like this :
populateJoin(joins) {
return joins.reduce((p, join) => {
return p.then(obj => {
let id = this.requestQuery[toCamelCase(join.as) + 'Id'] || obj[toSnakeCase(join.as) + '_id'] || obj[toSnakeCase(join.as + 's') + '_id'] || null;
if(id) {
return join.model.findOne({'where': { 'id': id }}).then(tmp => {
if (obj.dataValues[join.as]) {
return obj.dataValues[join.as];
} else {
obj.dataValues[join.as] = tmp;
return tmp; // 'tmp' will be `obj` at next iteration of the reduction.
}
return tmp; // 'tmp' will be `obj` at next iteration of the reduction.
});
} else {
return obj; // send unmodified obj to next iteration of the reduction.
}
});
}, Promise.resolve(this.databaseObject)) // starter promise for the reduction
.then(() => this.databaseObject); // useful though not essential to make the top level object available to the caller's .then() callback.
}
populateJoins() {
var promises = [];
for (let c in this.columns) {
let transformColumn = this.columns[c];
if (transformColumn.joins) {
promises.push(this.populateJoin(transformColumn.joins));
}
}
return Promise.all(promises);
}
i have created a tree select that shows a dijit.tree in the dropdown. Now I do not want the user to select a folder even if it is empty. User should only be able to select the end nodes or leaves. dijit.tree treats all empty folders as leafs. how do I get that sorted?
You need to override the _onClick or setSelected methods. This gets complicated if you use the multi-parental model ForestStoreModel.
See fiddle.net
Try doing as such, this will only work for select multiple false:
getIconClass: function fileIconClass(item, nodeExpanded) {
var store = item._S,
get = function() {
return store.getValue(item, arguments[0]);
};
// scope: dijit.Tree
if (item.root || get("isDir")) {
if (!item || this.model.mayHaveChildren(item) || get("isDir")) {
return (nodeExpanded ? "dijitFolderOpened" : "dijitFolderClosed");
} else {
return "dijitLeaf";
}
} else {
return "dijitLeaf";
}
},
onClick: function(item, treeNode, e) {
var store = item._S,
get = function() {
return store.getValue(item, arguments[0]);
};
if (get("isDir")) this.set("selectedItems", []);
}
Adapt as you see fit, matching your json data - in particular the isDir, the above works on a sample of json like this
{
identifier: 'id',
label: 'foo',
items: [
{
id: 'item1',
foo: 'file1',
isDir: false},
{
id: 'item2',
foo: 'emptyDir',
isDir: true},
{
id: 'item3',
foo: 'dir',
isDir: true,
children: [
{
id: 'item3_1',
foo: 'fileInDir',
isDir: false}
]}
]
}