I have a b-form-select field and emit my value-field to my parent, but I need the selected text-field too..
Here is the needed code to show what I mean:
In my template:
<b-form-select v-model="selected" :options="getOptions" text-field="Name" value-field="Rank"></b-form-select>
but if I console.log(this.selected), I get of course the value Rank which I have selected. But is it also possible to get the text-field ?
Here is my script to show how my selected works:
computed: {
getOptions() {
const array = [];
const person = this.data.find((i) => i.name === this.name);
for (let key in person.persons) {
array.push(person.persons[key]);
}
return array;
},
}
my json data:
[
{
"name": "XXX",
"persons": {
"1": {
"Name": "Max",
"Rank": "1"
},
"2": {
"Name": "Peter",
"Rank": "2"
},
"3": {
"Name": "Harry",
"Rank": "1"
},
"4": {
"Name": "Jake",
"Rank": "0"
}
}
},
]
As you have the value available, as well as the list of options you can simply add a new computed field to get the selected values text-field
computed: {
getOptions() {
const array = [];
const person = this.data.find((i) => i.name === this.name);
for (let key in person.persons) {
array.push(person.persons[key]);
}
return array;
},
selectedOption() {
if (!this.selected) {
return null;
}
return Object.values(this.getOptions).find((option) => {
return option.Rank === this.selected;
});
}
}
Then access selectedOption.Name or selectedOption.Rank. If you put the Name and Rank into variables / data attributes as well you can also make it more generic.
Update:
Changed to Object.values
Related
I want to create a nested filter in js
when I filter my array primary data is affected and changed but I need preliminary data to remove filters
my js code :
let result = companies;
result.map((item, i) => {212
let rows = [...result[i].table.table_rows].filter((item3) => {
return Object.keys(item3).some(i => item3[i][key] === value[key]);
});
result[i].table.table_rows = [...rows];
return result[i];
});
arrayFilter(result);
my data is:
{
"companies": [
{
"company": {
"name": "company 1"
},
"table": {
"table_rows": [
{
"cells": {
"product_name": "prod1",
"pa_size": "12"
}
},
{
"cells": {
"product_name": "prod2",
"pa_size": "15"
}
}
]
}
},
{
"company": {
"name": "company 2"
},
"table": {
"table_rows": [
{
"cells": {
"product_name": "prod2-1",
"pa_size": "12"
}
},
{
"cells": {
"product_name": "prod2-2",
"pa_size": "18"
}
}
]
}
}
]
}
I tried many ways to solve this problem, but I did not get the right answer
Your question is not clear, the point I have understand that you wanted to filter the array "table_rows" located inside each companies array object? map and filter returns new array, so the solution for this is:
result = result.companies.map((item, i) => {
const newItem = {...item};
let rows = newItem .table.table_rows.filter((item3) => {
return Object.keys(item3).some(i => item3[i][key] === value[key]);
});
newItem.table_rows = [...rows];
return newItem ;
});
arrayFilter(result);
This is input data, where i want filter a object by ID key
let myData = {
"nodeInfo":
{
"9":
{
"1": { "ID": "14835", "name": "Binod" },
"2": { "ID": "14836", "name": "Rahul" },
"3": { "ID": "14837", "name": "Sunil" },
},
"10":
{
"4": { "ID": "14839", "name": "Shikhar" },
"5": { "ID": "14840", "name": "Hari" },
"6": { "ID": "14841", "name": "Harsh" },
}
}
};
i want which object who have ID value 14835
so my result would be:: { "ID": "14835", "name": "Binod" }
This supports many levels of nested objects
function isObject(possibleObject) {
return typeof possibleObject === 'object' && possibleObject !== null
}
function find(data, key) {
for (const element of Object.values(data)) {
if (element.ID) {
if (element.ID === key) {
return element;
}
continue;
}
if (isObject(element)) {
const foundElement = find(element, key);
if (foundElement !== null) {
return foundElement;
}
}
}
// Not found
return null;
}
``
#Gluey1017 has provided a very good answer that will return the first occurrence of an object with the given ID key. In the following snippet I modified/extended his script to also collect multiple results should they exist:
const myData = {
"nodeInfo":
{
"9":
{
"1": { "ID": "14835", "name": "Binod" },
"2": { "ID": "14836", "name": "Rahul" },
"3": { "ID": "14837", "name": "Sunil" },
},
"10":
{
"4": { "ID": "14839", "name": "Shikhar" },
"5": { "ID": "14840", "name": "Hari" },
"6": { "ID": "14841", "name": "Harsh" },
},
"15":
{ "7": {
"8": { "ID": "14835" , "name": "Carsten" },
"9": { "ID": "14842" , "name": "someone" }
} }
}
};
function find(data,key){
const found=[]; // results array
function fnd(da) { // recursive function
for (const el of Object.values(da)){
if (el?.ID === key) found.push(el);
if (typeof el==='object' && el !== null) fnd(el);
}
}
fnd(data);
return found;
}
console.log(find(myData,"14835"));
Using an arrow function expression, what about
getter = ID => Object.values(
myData.nodeInfo
).map(
o => Object.values(o).filter(
v => v.ID === ID
)[0]
)
and then
> getter("14835")
< (2) [{…}, {…}]
And, depending on whether your identifiers are unique or not, you can actually do
> getter("14835")[0]
< {ID: '14835', name: 'Binod'}
Using spread operator to find item from a flat array of objects:
// get nodeInfo values
Object.values(myData.nodeInfo)
// reduce to flat array of objects
.reduce((acc,v) => [...acc, ...Object.values(v)],[])
// assuming ID is unique find object
.find(o => o.ID === "14835")
If the level is unknown, with data structured as above, recursion can be used to get to the level where objects have the desired properties.
Please notice that the function expects an array as its first parameter.
// check for the presence of the relevant keys
const findByID = (vals, id) => vals.some(o => 'ID' in o && 'name' in o)
// if present find the value
? vals.find(o => o.ID === id)
// else repeat with level below
: findByID(vals.reduce((acc,v) => [...acc, ...Object.values(v)],[]), id);
findByID(Object.values(myData), "14835");
I have an array called data that keeps users information. I want to filter it to return the best percentage of each user for me.how can I do this.
this is my array:
let data = [ {
"userId": "1",
"percent": 97.58,
},
{
"userId": "1",
"percent": 92.01,
},
{
"userId": "2",
"percent": 91.64,
},
{
"userId": "2",
"percent": 91.64,
},
{
"userId": "3",
"percent": 91.64,
}]
I would use reduce:
let data = [
{ "userId": "1", "percent": 97.58, },
{ "userId": "1", "percent": 92.01, },
{ "userId": "2", "percent": 91.12, },
{ "userId": "2", "percent": 91.64, },
{ "userId": "3", "percent": 91.45, }
]
const bestGrades = data.reduce((acc, cur) => {
acc[cur.userId] = acc[cur.userId] || 0; // initialise the entry
acc[cur.userId] = Math.max(acc[cur.userId],cur.percent); // take the greatest
return acc;
}, {})
console.log(bestGrades)
reduce is a useful method as it allows you to accumulate new information into a new object as you iterate over the array.
const data=[{userId:"1",percent:97.58},{userId:"1",percent:92.01},{userId:"2",percent:91.64},{userId:"2",percent:91.64},{userId:"3",percent:91.64}];
const out = data.reduce((acc, c) => {
// Grab the id and percentage from the current object
const { userId: id, percent } = c;
// If the initial object that you pass in (the accumulator)
// doesn't have a property with a key that matches the id
// set a new property with the percentage value
acc[id] = acc[id] || percent;
// If the value of the percentage of the current object
// is greater than the value set on the existing property
// update it
if (percent > acc[id]) acc[id] = percent;
// Return the accumulator for the next iteration
return acc;
}, {});
console.log(out);
this.StaticData = {
"values": [
{
"value": "test",
"label": "test"
},
{
"value": "aa",
"label": "bb"
},
{
"value": "cc",
"label": "dd"
}
]
};
I have above object of data. I wanted to return all object except currentIndex.
For example -
suppose in above objects, if I am going to edit 0th index values,
and I have updated "value": "rest", instead of "value": "test" and
"label": "test" need to keep as it is. So in that case,
it will allow to update the values.
{
"value": "rest",
"label": "test"
},
But if I tried to enter "label": "bb" and "label": "dd",
so it will return false, because these values are already available in above objects.
isLabelExist() {
const formData = this.editStaticParametersForm.value;
const currentIndex: number = this.StaticData.values.indexOf(this.selectedRowValue);
if (formData.label_value && this.StaticData) {
var isPresent = this.StaticData.values.some(function (el) {
return el.label === formData.label_value
});
if (isPresent) {
return false;
}
}
return true;
}
using find (or some) you can check the "index" (add a second argument to the function find), so,
var isPresent = this.StaticData.values.some(function (el,i) {
return el.label === formData.label_value && i!=currentIndex
});
Really in .ts we use arrow flat and use const or let, not var
const isPresent = this.StaticData.values.some((el,i)=> {
return el.label === formData.label_value && i!=currentIndex
});
Or
const isPresent = this.StaticData.values.some(
(el,i)=> el.label === formData.label_value && i!=currentIndex);
I'm trying to use paularmstrong/normalizr on JSON that comes from FractalTransformer and whose nested childs have "data" attribute. Example of JSON:
{
"data": {
"object": "Offer",
"id": "5g6aqocew4qjzl40",
"real_id": 26,
"name": "Random Name",
"created_at": {
"date": "2019-06-18 11:13:08.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"readable_created_at": "1 year ago",
"site": {
"data": {
"object": "Site",
"id": "65zody8vj29vlegd",
"name": "Test Site",
"real_id": 1
}
},
"countries": {
"data": [
{
"object": "Country",
"code": "US",
"name": "United States"
},
{
"object": "Country",
"code": "DE",
"name": "Germany"
}
]
}
},
"meta": {
"include": [
"site",
"countries"
],
"custom": []
}
}
Schemas I use:
export const offerSchema = new schema.Entity('offers')
export const siteSchema = new schema.Entity('sites', {}, {
processStrategy: (value) => {
return { ...value.data }
},
idAttribute: (value) => {
return value.data.id
},
})
export const countrySchema = new schema.Entity('countries')
offerSchema.define({
site: siteSchema,
countries: [countrySchema],
})
Now the issue is that I remove 'data' from the site since it's just one object successfully, but I can't do it in the country case. Whatever I tried with custom processStrategy fails, as country is object that has data which is array (I assume this is where the issue is, going from Entity to Array). And in idAttribute function I always get complete array so can't determine the ID of single entry. So the end result is that the ID of countries is undefined. Any ides?
I actually managed with another approach. I added processStrategy on the parent, 'Offer' in this case, so all 'data' parts get stripped before they reach other child schemas.
const normalizrStripDataOptions = {
processStrategy: (value) => {
const ret = { ...value }
Object.keys(ret).forEach((key) => {
if (ret[key] !== null) {
if (ret[key].data && Array.isArray(ret[key].data)) {
ret[key] = [...ret[key].data]
}
if (ret[key].data && typeof ret[key].data === 'object') {
ret[key] = { ...ret[key].data }
}
}
})
return ret
},
}
export const offerSchema = new schema.Entity('offers', {}, normalizrStripDataOptions)
export const siteSchema = new schema.Entity('sites')
export const countrySchema = new schema.Entity('countries')
offerSchema.define({
site: siteSchema,
countries: [countrySchema],
})