Limit select option with another select with angularjs - javascript

My object from database is coming like this:
[
{
"id": 8,
"concessionaria": {
"id": 1,
"nome": "asda"
},
"plano": {
"id": 1,
"sigla": "B3",
"nome": "tetes"
},
"descricao": "45987",
"enable": true
},
{
"id": 7,
"concessionaria": {
"id": 2,
"nome": "teste2"
},
"plano": {
"id": 3,
"sigla": "b4",
"nome": "Teste 2"
},
"descricao": "qweqwe",
"enable": true
},
{
"id": 6,
"concessionaria": {
"id": 2,
"nome": "teste2",
"estado": "ES"
},
"plano": {
"id": 2,
"sigla": "B3",
"nome": "Consumidores"
},
"descricao": "werwerw",
"enable": true
}
]
And i need to show two select, to choose the "concessionaria" and then the "planos" it has.
How can i do it since the "concessionaria" comes multiple times as the "plano" changes?

You have to create new model.
This sample show to you how can convert or create new model to get the concessionaria and plano as array to make them as select option
var app = angular.module("app", []);
app.controller("ctrl", [
"$scope",
function($scope) {
var json = [{
"id": 8,
"concessionaria": {
"id": 1,
"nome": "asda"
},
"plano": {
"id": 1,
"sigla": "B3",
"nome": "tetes"
},
"descricao": "45987",
"enable": true
},
{
"id": 7,
"concessionaria": {
"id": 2,
"nome": "teste2"
},
"plano": {
"id": 3,
"sigla": "b4",
"nome": "Teste 2"
},
"descricao": "qweqwe",
"enable": true
},
{
"id": 6,
"concessionaria": {
"id": 2,
"nome": "teste2",
"estado": "ES"
},
"plano": {
"id": 2,
"sigla": "B3",
"nome": "Consumidores"
},
"descricao": "werwerw",
"enable": true
}
];
$scope.model = {
concessionaria: [],
plano: []
};
angular.forEach(json, function(item) {
var concessionaria = item.concessionaria;
var plano = item.plano;
$scope.model.concessionaria.push(concessionaria);
$scope.model.plano.push(plano);
});
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<label>concessionaria</label>
<select ng-model="form.concessionaria" ng-options="item as item.nome for item in model.concessionaria"></select> {{form.concessionaria}}
<hr />
<label>plano</label>
<select ng-model="form.plano" ng-options="item as item.nome for item in model.plano"></select> {{form.plano}}
</div>

You can use limitTo filter.
For example: ng-repeat="item in items | limitTo 2"
For more informations: https://www.w3schools.com/angular/ng_filter_limitto.asp

You will need two selects, populate the first select with distinct values of concessionaria, and once user select a value from the first select you will have the id of concessionaria, then depending on that value you can populate the second select box with different plano. So if user selects a concessionaria with id 2 your second select box will be populated with two plano (one with plano id 2 and other with plano id 3)

Related

How can I convert an array of objects to array with a unique id in javascript?

I have a array of object like this :
{
"data": [
{
"id": 1,
"from": "2022-08-01",
"to": "2022-08-05",
"description": "test 1",
"files": [
{
"id": 1,
"hospital_name": "hospital 11",
"hospital_id": 11,
"period_id": 1
},
{
"id": 2,
"hospital_name": "hospital 11",
"hospital_id": 11,
"period_id": 1
}
]
},
{
"id": 2,
"from": "2022-08-06",
"to": "2022-08-10",
"description": "test 2",
"files": [
{
"id": 3,
"hospital_name": "hospital 12",
"hospital_id": 12,
"period_id": 2
},
{
"id": 4,
"hospital_name": "hospital 12",
"hospital_id": 12,
"period_id": 2
}
]
}
]
}
I want to convert the array to be like this :
{
"data": [
{
"id": 1, // this is period id
"hospital_name": "hospital 11",
"hospital_id": 11,
"from": "2022-08-01",
"to": "2022-08-05",
"description": "test 1"
},
{
"id": 2,
"hospital_name": "hospital 12",
"hospital_id": 12,
"from": "2022-08-06",
"to": "2022-08-10",
"description": "test 2"
}
]
}
So I expect the results like that
I try to type my code like this :
data.flatMap((period) =>
period.files.map((file) => ({
id: period.id,
hospital_name: file.hospital_name,
hospital_id: file.hospital_id,
from: period.from,
to: period.to,
description: period.description,
}))
)
But the problem is my code show duplicate id
How can I solve my problem?
Note :
Every period only has one hospital id
You don't need flatMap, just run map on periods and for each period, pick the first file to extract hospital_id and hospital_name like this:
data.map(period => {
const file = period.files[0];
return {
id: period.id,
hospital_name: file.hospital_name,
hospital_id: file.hospital_id,
from: period.from,
to: period.to,
description: period.description,
}
});
You can filter the last result like:
const j = {
"data": [{
"id": 1,
"from": "2022-08-01",
"to": "2022-08-05",
"description": "test 1",
"files": [{
"id": 1,
"hospital_name": "hospital 11",
"hospital_id": 11,
"period_id": 1
},
{
"id": 2,
"hospital_name": "hospital 11",
"hospital_id": 11,
"period_id": 1
}
]
},
{
"id": 2,
"from": "2022-08-06",
"to": "2022-08-10",
"description": "test 2",
"files": [{
"id": 3,
"hospital_name": "hospital 12",
"hospital_id": 12,
"period_id": 2
},
{
"id": 4,
"hospital_name": "hospital 12",
"hospital_id": 12,
"period_id": 2
}
]
}
]
}
console.log(j.data.flatMap((period) =>
period.files.map((file) => ({
id: period.id,
hospital_name: file.hospital_name,
hospital_id: file.hospital_id,
from: period.from,
to: period.to,
description: period.description,
}))
).filter((value, index, self) =>
index === self.findIndex((t) => (
t.id === value.id
))))
Reference:
Array.prototype.filter()
Since the objects in the files array are identical (other than the id) you can destructure the properties from the data array, and (within that) the first object of each files array, and return a new object.
const data={data:[{id:1,from:"2022-08-01",to:"2022-08-05",description:"test 1",files:[{id:1,hospital_name:"hospital 11",hospital_id:11,period_id:1},{id:2,hospital_name:"hospital 11",hospital_id:11,period_id:1}]},{id:2,from:"2022-08-06",to:"2022-08-10",description:"test 2",files:[{id:3,hospital_name:"hospital 12",hospital_id:12,period_id:2},{id:4,hospital_name:"hospital 12",hospital_id:12,period_id:2}]}]};
const out = data.data.map(obj => {
const {
from,
to,
files: [{ period_id, id, ...rest }],
description
} = obj;
return { id: period_id, from, to, description, ...rest }
});
console.log(out);
Additional information
Destructuring assignment
Rest parameters
Spread syntax

Javascript object, return the updated object that contains a value in nested arrays

I have the following object:
{
"id": 2,
"name": "tes name",
"status": 0,
"categories": [
{
"category_id": 1,
"name": "taxes",
"description": "taxes",
"keys": [
{
"key_id": 1,
"value": "preset unique value if not overridden, real text value"
},
{
"key_id": 2,
"value": "test name"
}
]
},
{
"category_id": 2,
"name": "surcharges",
"description": "surcharges",
"keys": [
{
"key_id": 3,
"value": "preset value if not overridden, real text value"
},
{
"key_id": 5,
"value": ""
}
]
},
{
"category_id": 3,
"name": "errors",
"description": "errors",
"keys": [
{
"key_id": 6,
"value": "preset value if not overridden, real text value"
},
{
"key_id": 10,
"value": "unique value to test search"
}
]
}
]
}
What I need to do is update the object based on: it must contain the key in the keys array if only key.value contains the string 'unique' otherwise the array must not contain that key in the keys array.
Expected output is:
{
"id": 2,
"name": "tes name",
"status": 0,
"categories": [
{
"category_id": 1,
"name": "taxes",
"description": "taxes",
"keys": [
{
"key_id": 1,
"value": "preset unique value if not overridden, real text value"
}
]
},
{
"category_id": 3,
"name": "errors",
"description": "errors",
"keys": [
{
"key_id": 10,
"value": "unique value to test search"
}
]
}
]
}
I tried nested filter but it won't work for me, always getting the same object as it is.
my code:
var result = obj.categories.filter(function(category) {
return category.keys.filter(function(key) {
return key.value.includes(action.payload)
});
});
Any suggestions or where am I going wrong?
You could take a nested approach and reduce the array by checking the nested filterd array.
This solution does not mutate the original data.
var data = { id: 2, name: "tes name", status: 0, categories: [{ category_id: 1, name: "taxes", description: "taxes", keys: [{ key_id: 1, value: "preset unique value if not overridden, real text value" }, { key_id: 2, value: "test name" }] }, { category_id: 2, name: "surcharges", description: "surcharges", keys: [{ key_id: 3, value: "preset value if not overridden, real text value" }, { key_id: 5, value: "" }] }, { category_id: 3, name: "errors", description: "errors", keys: [{ key_id: 6, value: "preset value if not overridden, real text value" }, { key_id: 10, value: "unique value to test search" }] }] },
filtered = Object.assign({}, data, {
categories: data.categories.reduce((r, o) => {
var keys = o.keys.filter(({ value }) => value.includes('unique'));
if (keys.length) {
r.push(Object.assign({}, o, { keys }));
}
return r;
}, [])
});
console.log(filtered);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hope this works for you.
Also filter is not in place method, so even though you are filtering Categories.keys and returning it , it wont be modified.
Once filtered, we are using categories.keys.length to filter categories with empty keys
var obj = {
"id": 2,
"name": "tes name",
"status": 0,
"categories": [
{
"category_id": 1,
"name": "taxes",
"description": "taxes",
"keys": [
{
"key_id": 1,
"value": "preset unique value if not overridden, real text value"
},
{
"key_id": 2,
"value": "test name"
}
]
},
{
"category_id": 2,
"name": "surcharges",
"description": "surcharges",
"keys": [
{
"key_id": 3,
"value": "preset value if not overridden, real text value"
},
{
"key_id": 5,
"value": ""
}
]
},
{
"category_id": 3,
"name": "errors",
"description": "errors",
"keys": [
{
"key_id": 6,
"value": "preset value if not overridden, real text value"
},
{
"key_id": 10,
"value": "unique value to test search"
}
]
}
]
}
var result = obj.categories.filter(function(category) {
category['keys']=category.keys.filter(function(key) {
return key.value.includes('unique')
})
return category['keys'].length
});
console.log(result)
The output of the function given to filter() should always return a boolean that indicates if the value should be filtered out or not. Your code
return category.keys.filter(function(key) {
return key.value.includes(action.payload)
});
returns the filtered key lists, but then the outer filter function uses these lists as the filter value. As long as the filtered list contains any element, it will be converted to true and therefore the category will not be filtered out.
The actual code should instead look something like this:
obj.categories.forEach(function(category){
category.keys = category.keys.filter(function(key){
return key.value.includes(action.payload);
});
});
This iterates over all key arrays and applies the filter to each one.
If you also want to filter out categories that would then have empty key array, you can add the outer filter back in but keep the assignment to category.keys:
obj.categories = obj.categories.filter(function(category){
return (category.keys = category.keys.filter(function(key){
return key.value.includes(action.payload);
}););
});
This works because the return value of the assignment is the value that is assigned to category.keys, so the filter will once again keep only those categories that still contain keys.

Parsing categories tree into HTML select tag

I have this categories tree input :
"categories": [
{
"text": "Upstate",
"id": 3,
"category_parent_id": 0,
"children": []
},
{
"text": "North",
"id": 2,
"category_parent_id": 0,
"children": [
{
"text": "Child N 1",
"id": 5,
"category_parent_id": 2,
"children": [
{
"text": "Another Child 1",
"id": 11,
"category_parent_id": 5,
"children": []
},
{
"text": "Another Child 2",
"id": 10,
"category_parent_id": 5,
"children": []
}
]
},
{
"text": "Activity",
"id": 4,
"category_parent_id": 2,
"children": []
}
]
},
{
"text": "Health",
"id": 1,
"category_parent_id": 0,
"children": [
{
"text": "Good Health",
"id": 9,
"category_parent_id": 1,
"children": []
},
{
"text": "Bad Health",
"id": 8,
"category_parent_id": 1,
"children": []
}
]
}
]
So, now I want to populate my select box like this :
Upstate
North
-Child N 1
--Another Child 1
--Another Child 2
-Activity
Health
-Good Health
-Bad Health
So, how can I parse through the input tree and populate the select box with these values? Any algorithm or recursive function approach I can use to achieve this ?
make a recursive function
flatCategories(data: any[], children: any[], index: number) {
data=data||[];
children.forEach(x => {
data.push({ id: x.id, text: '-'.repeat(index) + x.text });
if (x.children && x.children.length)
this.flatCategories(data, x.children, index + 1)
})
return data
}
You can use like
let dataFlat=this.flatCategories([], this.data.categories, 0);
console.log(this.dataflat.map(x => x.text))
If you want to create a recursive component it's easy (but in case of select not work)
#Component({
selector: 'item-line',
template: `
<div *ngFor="let item of children" [style.margin-left]="index+'rem'">
{{item.text}}
<item-line *ngIf="item.children" [children]="item.children" [index]="index+1">
</item-line>
</div>
`,
})
export class HelloComponent {
#Input() children:any[]
#Input() index:number=0;
}
You can see in stackblitz

Make subcategory as array in object of array

I'm working on django rest and angular. This json array is coming from server and contains category and subcategory values.
my code will create category and related subcategory in separate keys of array. But i want keep subcategory as a array in object in same object.
Result should be like this:
[{"title":"title of category","sub":[array of related sub]} , ...]
mycode:
public data = SERVERRESPONE;
public categories = [];
this.data.filter(c => c.parent_id === null).map(c => <{ title: {}; subcategories: {} }>{
title: {"title":c.title},
subcategories: this.data.filter(sc => sc.parent_id === c.cat_id).map(sc => sc.title)
}).forEach(c => {
this.categories.push([c.title, [c.subcategories]]);
});
server response :
[
{
"id": 5,
"cat_id": 0,
"parent_id": null,
"title": "web development"
},
{
"id": 6,
"cat_id": 1,
"parent_id": null,
"title": "android development"
},
{
"id": 7,
"cat_id": null,
"parent_id": 0,
"title": "php"
},
{
"id": 8,
"cat_id": null,
"parent_id": 1,
"title": "java"
}
]
it is nice question but it has very easy solution!
const array = [
{
"id": 5,
"cat_id": 0,
"parent_id": null,
"title": "web development"
},
{
"id": 6,
"cat_id": 1,
"parent_id": null,
"title": "android development"
},
{
"id": 7,
"cat_id": null,
"parent_id": 0,
"title": "php"
},
{
"id": 8,
"cat_id": null,
"parent_id": 1,
"title": "java"
}
]
let result = []
for (let key of array) {
if (key.parent_id === null) {
let new_key = key,
sub = []
for (let iterator of array)
if (iterator.parent_id === key.cat_id)
sub.push(iterator)
new_key.sub = sub
result.push(new_key)
}
}
console.log(result)

Add a property into a JSON object JS

I have this JSON:
{
"id": 10,
"name": "Color test2",
"seed_id": 1,
"season_id": 2,
"description": null,
"work_schedule_type_id": 2,
"color": "#00A946",
"active": false,
"starred": true,
"phases": [{
"id": 2,
"name": "Phase2",
"work_schedule_type_id": 2,
"phase_color": "#343434",
"phase_order_of_operations": 1,
"description": "TEST PHASE TYPE2",
"isExpanded": false,
"$$hashKey": "object:1387"
}]
}
I need add a property tasks for each phase in phases. How I can do this?
angular.forEach(obj.phases, function(item) { item.tasks = your_val } );
This approach adds the tasks from an Array.
var obj = {
"id": 10,
"name": "Color test2",
"seed_id": 1,
"season_id": 2,
"description": null,
"work_schedule_type_id": 2,
"color": "#00A946",
"active": false,
"starred": true,
"phases": [{
"id": 2,
"name": "Phase2",
"work_schedule_type_id": 2,
"phase_color": "#343434",
"phase_order_of_operations": 1,
"description": "TEST PHASE TYPE2",
"isExpanded": false,
"$$hashKey": "object:1387"
}]
}
var tasks = ["Task1", "Task2"];
obj.phases.forEach(p => p.tasks = tasks);
console.log(obj.phases);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Assuming your JSON object is named json, the code would look something like this:
for (phase of json.phases) {
phase.task = "somevalue";
}

Categories