Select multiple display names instead of IDs using AngularJS - javascript

I have a multiple select like this :
<select ng-model="listProds" multiple>
<option value="10">product 1</option>
<option value="25">product 2</option>
<option value="35">product 3</option>
<option value="48">product 4</option>
</select>
The values are the Ids for these products ( and this selectbox is generated using PHP )
& I've got this simple code in my app.js file :
var app = angular.module('myapp', []);
app.controller("PurchasesController", function($scope) {
// Init products Array
$scope.listProds = [];
});
When I display the listProds like this {{ listProds }}, I get an array containing the current selected items, but it only shows the Ids like this if I select all of them ["10","25","35","48"].
<fieldset ng-show="listProds.length > 0">
<div data-ng-repeat="p in listProds track by $index">
{{ p }} <!– Or –> {{ listProds[$index] }}
<input type="text" name="pr{{ listProds[$index] }}" />
<input type="text" name="qt{{ listProds[$index] }}" />
</div>
</fieldset>
This code generate two text boxes to enter the Price and Quantity for each Product in selected from the selectbox. So instead of using {{ p }} or {{ listProds[$index] }} and displaying the Product Id, I want to display there the Product name.
Thank you in advance.

You can create two lists: one for all your products and a separate list for the selected products:
$scope.listProds = [
{ key: 10, value: 'Product 1' },
{ key: 25, value: 'Product 2' },
{ key: 35, value: 'Product 3' },
{ key: 45, value: 'Product 4' }
];
$scope.selectedProds = [];
Now in your markup, instead of writing out each option in your select manually, you can use ng-options to generate your options. Using this approach, you are basically saying that each option is an object, and you want to use the objects value as the display name.
<select ng-model="selectedProds" ng-options="prod.value for prod in listProds" multiple>
Now your $scope.selectedProds array will contain the product objects, and not just they keys. So now you can display the name easily:
<fieldset ng-show="selectedProds.length > 0">
<div data-ng-repeat="p in selectedProds track by $index">
{{ p.value }}
<input type="text" name="pr{{ selectedProds[$index] }}" />
<input type="text" name="qt{{ selectedProds[$index] }}" />
</div>
</fieldset>
Not sure what your want the name attribute of the inputs to be, but I hope you get the idea.

Try this.
var app = angular.module('selTest', []);
app.controller('MainCtrl', function($scope) {
$scope.selectedProducts = [];
$scope.products = [
{ id:1, name: 'POne' },
{ id:2, name: 'PTwo' },
{ id:3, name: 'PThree' }
];
$scope.getNames = function(prods) {
return prods.map(function(p) {
return p.name;
});
};
$scope.getIds = function(prods) {
return prods.map(function(p) {
return p.id;
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="selTest">
<div ng-controller="MainCtrl">
<select name="products"
class="form-control input-sm"
ng-model="selectedProducts"
ng-options="p.name for p in products track by p.id"
ng-style="{'width':'100%'}" multiple>
</select>
<div>Selected Names: {{ getNames(selectedProducts) }}</div>
<div>Selected Ids: {{ getIds(selectedProducts) }}</div>
</div>
</div>

Related

How to sum selected values in option tag

So I have a v-for loop and 7 different documents from mongo database. Every document contains one food and for each food it has specific number of calories. And I want to sum all the selected calories. For example I got a variable food.calorie_number. Okay so I have something like this:
<tr>
<td v-for="(food) in fetch_breakfast.slice(8,15)" :key=food.id>Meal <p style="border-top: 3px solid #dddddd;">
<select class="form-select" aria-label="Default select example">
<option selected>Select your food</option>
<option v-bind:value="food.id">{{food.food}}</option>
<!-- Every meal has food.calorie_number -->
<option value="3"></option>
</select>
</p></td>
<p>Calorie sum: {{Sum}}</p>
</tr>
I wanted to do something like this: Sum = Sum + food.calorie_number but i didn't get the final solution because I don't know how to do it for a specific element generated by v-for.
If I understood you correctly try like following snippet (with computed and method for selection) :
new Vue({
el: '#demo',
data() {
return {
fetch_breakfast: [{id: 1, food: 'apple', calorie_number: 80}, {id: 2, food: 'peach', calorie_number: 70}, {id: 3, food: 'carrot', calorie_number: 90}],
selected: []
}
},
computed: {
sum() {
return this.selected.reduce((acc, curr) => acc + curr.calorie_number, 0)
}
},
methods: {
getSum(food) {
const idx = this.selected.findIndex(s => s.id === food.id)
idx > -1 ? this.selected.splice(idx, 1) : this.selected.push(food)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<table>
<tr>
<td v-for="food in fetch_breakfast" :key=food.id>Meal
<p>
<select class="form-select" #change="getSum(food)">
<option selected>Select your food</option>
<option :value="food.id">{{ food.food }}</option>
</select>
</p>
</td>
<p>Calorie sum: {{ sum }}</p>
</tr>
</table>
</div>
First you have v-for on the wrong element because that way it will return 7 select. if you want to have seven options put v-for in select but to have a default option that is not affected by the loop put in option like this:
then do your logic and fetch in either computed value
var selector = new Vue({
el: '#selector',
data: {
selected: null,
meals: [
{'id':1,
"name":"food_name_1",
"calories":"1.6g"
},
{'id':2,
"name":"food_name_g",
"calories":"1.8g"
},
{'id':3,
"name":"food_name_v",
"calories":"1.9g"
},
{'id':9,
"name":"food_name_v",
"calories":"1.66g"
},
{'id':11,
"name":"food_name_y",
"calories":"1.1g"
},
]
},
computed:{
selected_food(){
let id = this.selected
let selected_meal = this.meals.find(meal => meal.id === id)
return selected_meal
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="selector">
<select :default="0" v-model="selected">
<option selected="selected" :value=null>select meal</option>
<option v-for="(meal, key) in meals" :key=key :value="meal.id">
{{ meal.name }}
</option>
</select>
<br>
<br>
<div v-if="selected">
<span > Selected food : {{selected_food.name}}</span> </br>
<span > Selected food Calory : {{selected_food.calories}}</span>
</div>
<span v-else>Please select a meal</span>
</div>

Dynamically generate nested inputs in form

I'm very new into frontend, so I appreciate any help.
I'm trying to build a form, where user select an option from element and then depending on condition, dynamically generates another one (and some other inputs) as a child elements.
Finally what I'm trying to get is JSON with nested structure. E.g.
fields: [{type: 'List', value: [{type: 'Map', value: [{type: 'Integer', value: 5}, {type: 'List', value: [and so on...]]]}]
I have already started to code it in native JS and this is what I have so far (snippet below).
I want to release something similar with VUE.js library (or maybe someone can tell me any other useful libraries), cuz I want to control visibility of my inputs based on some conditions and some other useful features...but I dont know how to dynamically push elements into nested into nested and so on...I appriciate any help, any ideas and any examples. Thanks!
let template = `
<select name="type" onChange="createChildElement(this)" aria-label="Select type">
<option value="List">Select type</option>
<option value="List">List</option>
<option value="Map">Map</option>
<option value="Integer">Integer</option>
</select>
<select name="method" aria-label="Метод генерации">
<option value="Static">Static</option>
<option value="Random">Random</option>
<option value="Range">Range</option>
</select>
<input name="size" type="text" placeholder="Size">
<input name="value" type="text" placeholder="Value">
`;
function createChildElement(e) {
if(e.value == "List") {
var x = document.createElement('ul');
var z = document.createElement('li');
z.insertAdjacentHTML( 'beforeend', template );
x.appendChild(z);
e.parentNode.appendChild(x);
}
if(e.value == "Map") {
var x = document.createElement('ul');
var z = document.createElement('li');
z.insertAdjacentHTML( 'beforeend', template );
x.appendChild(z);
var y = document.createElement('ul');
var n = document.createElement('li');
n.insertAdjacentHTML( 'beforeend', template );
y.appendChild(n);
e.parentNode.appendChild(x);
e.parentNode.appendChild(y);
}
}
<body>
<div id="main-container">
<ul><li><div class="singleton-card ml-2">
<select name="type" onChange="createChildElement(this)" aria-label="Select type">
<option value="List">Select type</option>
<option value="List">List</option>
<option value="Map">Map</option>
<option value="Integer">Integer</option>
</select>
<select name="method" aria-label="Метод генерации">
<option value="Static">Static</option>
<option value="Random">Random</option>
<option value="Range">Range</option>
</select>
<input name="size" type="text" placeholder="Size">
<input name="value" type="text" placeholder="Value">
</div></li></ul>
</div>
</body>
I just found this example (https://codesandbox.io/s/github/vuejs/vuejs.org/tree/master/src/v2/examples/vue-20-tree-view?from-embed), I want to build something similar, but as a form with selects and inputs (just like my snippet example).
If I understand correctly, you're trying to create dependent dropdowns. You can check the following codepen for creating a dependent dropdown in vue.js
https://codepen.io/adnanshussain/pen/KqVxXL
JS
var model_options = {
1: [{ text: "Accord", id: 1 }, { text: "Civic", id: 2 }],
2: [{ text: "Corolla", id: 3 }, { text: "Hi Ace", id: 4 }],
3: [{ text: "Altima", id: 5 }, { text: "Zuke", id: 6 }],
4: [{ text: "Alto", id: 7 }, { text: "Swift", id: 8 }]
};
var makes_options = [
{ text: "Honda", id: 1 },
{ text: "Toyota", id: 2 },
{ text: "Nissan", id: 3 },
{ text: "Suzuki", id: 4 }
];
var vm_makes = new Vue({
el: "#app",
data: {
make: null,
model: null,
makes_options: makes_options,
model_options: model_options,
},
watch: {
make: function(event) {
$('#vehicle-models').dropdown('clear');
}
}
});
$('.ui.dropdown').dropdown();
HTML
<div id="app" class="ui grid">
<div class="row">
<div class="column">
<div class="ui label">Vechicle Make</div>
<select class="ui dropdown" v-model="make" id="vehicle-makes">
<option v-for="option in makes_options" v-bind:value="option.id">
{{ option.text }}
</option>
</select>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui label">Vechicle Model</div>
<select class="ui dropdown" id="vehicle-models" v-model="model">
<option
v-for="option in model_options[make]"
:value="option.id"
:key="option.id"
>
{{ option.text }}
</option>
</select>
</div>
</div>
</div>

Hide option when selected by another Select

I have two select's who uses the same list. When i choose the option "Foo" from select A the same option "Foo" must be hidden on select B. Any ideia how to do it with AngularJS ? I'm trying something like this
<div class="col-md-6">
<label>
Testemunha 1 :
</label>
<select select-normal data-placeholder="..." ng-model="notificacaoOrientativa.testemunha1"
ng-options="obj as obj.pessoa.nome for obj in lstTestemunha">
<option></option>
</select>
</div>
<div class="col-md-6">
<label>
Testemunha 2 :
</label>
<select select-normal data-placeholder="..." ng-model="notificacaoOrientativa.testemunha2"
ng-options="obj as obj.pessoa.nome for obj in lstTestemunha ">
<option></option>
</select>
</div>
$scope.esconderTestemunhaSelecionada = function(obj){
if($scope.lstTestemunha.includes(obj)){
$scope.lstTestemunha.style.display = "none";
return $scope.lstTestemunha;
}
}
You could use a filter on your second select. This will filter the items in the second select such that the item selected in the first does not appear. If you need it to be more complex (for example, this will cause the second select to not have any options until something is selected in the first select which may be an undesirable side effect) you can always write your own custom filter.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.selectItems = [];
$scope.selectedItemA = {};
$scope.selectedItemB = {};
for (let i = 1; i <= 10; i++) {
$scope.selectItems.push({
id: i,
name: 'Item #' + i
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div>
Select Item A:
<select ng-model="selectedItemA" ng-options="item as item.name for item in selectItems"></select>
</div>
<div>
Select Item B:
<select ng-model="selectedItemB" ng-options="item as item.name for item in selectItems | filter: { id: '!' + selectedItemA.id }"></select>
</div>
</div>
I solved this problem not the way that i'd like but works fine.
<div class="col-md-6">
<label>
Testemunha 1 :
</label>
<select select-normal data-placeholder="..." ng-model="notificacaoOrientativa.testemunha1"
ng-options="obj as obj.pessoa.nome for obj in lstTestemunha">
<option></option>
</select>
</div>
<div class="col-md-6">
<label>
Testemunha 2 :
</label>
<select select-normal data-placeholder="..." ng-model="notificacaoOrientativa.testemunha2" ng-disabled="!notificacaoOrientativa.testemunha1"
ng-options="obj as obj.pessoa.nome for obj in lstTestemunha | filter: {pessoa:{ id: '!' + notificacaoOrientativa.testemunha1.pessoa.id }}">
<option></option>
</select>
</div>
I'm forcing the user to set the first select and filter the second according to the first.
By the way, sry my poor english.

AngularJS unique filter not working

I have the following code and I cant get it to work with unique filter.
Also on jsfiddle it isn't working. In my HTML, the select is populated but unique filter is not working.
https://jsfiddle.net/krayziekry/sw8dvy3u/
Thank you
<div ng-app="example" ng-controller="exampleCtrl">
<!-- Select Basic -->
<div class="form-group span6">
<label class="control-label" for="from">Calatorind de la</label>
<div>
<select id="from" name="from" class="form-control" ng-model="selected.valp">
<option value="">Selecteaza...</option>
<option ng-repeat="rec in myRecs | filter: {vals: selected.vals} | orderBy:'plecare' | unique: 'plecare'" value="{{rec.valp}}">{{rec.plecare}}</option>
</select>
</div>
</div>
<!-- Select Basic -->
<div class="form-group span6">
<label class="control-label" for="to">catre</label>
<div>
<select id="to" name="to" class="form-control" ng-model="selected.vals">
<option value="">Selecteaza...</option>
<option ng-repeat="rec in myRecs | filter: {valp: selected.valp} | orderBy:'plecare'" value="{{rec.vals}}">{{rec.sosire}}</option>
</select>
</div>
</div>
</div>
<script>
angular.module('example', []).controller('exampleCtrl', function($scope) {
$scope.myRecs = [{
valp: 'AHO',
plecare: 'Alghero (AHO)',
sosire: 'Torino - Caselle (TRN)',
vals: 'TRN'
}, {
valp: 'ATH',
plecare: 'Atena (ATH)',
sosire: 'Constanta (CMD)',
vals: 'CMD'
}, {
valp: 'ATH',
plecare: 'Atena (ATH)',
sosire: 'Larnaca (LCA)',
vals: 'LCA'
}, {
valp: 'ATH',
plecare: 'Atena (ATH)',
sosire: 'Londra - Luton (LTN)',
vals: 'LTN'
}];
});
</script>
As far i Know the unique filter needs to be called from another module 'ui.filters'.
Sorry if my english its not hat good.
I forked your jsfiddle here
You will need to create a custom filter like this:
.filter('unique', function() {
return function(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if (keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
})
And use it like this:
<option ng-repeat="rec in myRecs | unique: 'valp' | orderBy:'plecare'" value="{{rec.valp}}">

Disable optgroup of multiple select which has specific label

I have taken a select list with multiple option using ng-options. I am using it as below:
<select ng-options="c as c.Text for c in ReceiverList track by c.Value" ng-model="ReceiverUserID" class="form-control" id="ddlReceiverUserID" ng-change="GetWorkers(ReceiverUserID, SenderUserID,'receiver')">
<option value="">--Select Supervisor--</option>
</select> <!-- Parent Drop Down-->
<select multiple ng-options="c as c.Text group by c.Group
for c in receiveList track by c.Value" ng-model="Workers"
class="form-control" id="ddlWorkers" size="10">
</select> <!-- Child Drop Down -->
This select dropdown get filled when I select some item from another dropdown.(It's a kind of cascaded dropdown). Filling it like below:
$scope.GetWorkers = function (objA, objB, ddlType) {
$http.post("user/Workers/", { userID: objA.Value })
.success(function (data, status, headers, config) {
if (ddlType == 'sender') {
$scope.sendList = data;
} else {
$scope.receiveList = data;
$('#ddlWorkers optgroup[label="Current Users"] option').prop('disabled', true); // Not working
}
})
.error(function (data, status, headers, config) {
showToast(ToastType.error, "Error occured while fetching workers.", "Failure");
});
}
I want to disable child dropdown's specific group items. So I tried below code but it is not working:
$('#ddlWorkers optgroup[label="Current Users"] option').prop('disabled', true);
I don't know how do I disable specific group items of select whenever its data changes or new data loaded.
Here is HTML output in which I want to disable all optgroup[label="Current Users"] members:
<select multiple="" ng-options="c as c.Text group by c.Group for c in receiveList track by c.Value" ng-model="Workers" class="form-control ng-pristine ng-valid" id="ddlWorkers" size="10">
<optgroup label="Current Users">
<option value="4118">Kevins Numen</option>
<option value="4119">ggdfg fdgdfg</option>
</optgroup>
<optgroup label="New Users">
<option value="1093">Case Worker</option>
</optgroup>
</select>
I don't know much about angularjs or ng-options, but it seems that everybody else used some timeout to let the process populate the received data to the input, and you can try something this like others:
...
} else {
$scope.receiveList = data;
setTimeout(function(){
$('#ddlWorkers optgroup[label="Current Users"] option')
.prop('disabled', true); // Not working
}, 100);
}
...
maybe not similar but good to have a look here:
is there a post render callback for Angular JS directive?
You need to customize your code and also JSON Object
<div ng-controller="AjaxCtrl">
<h1>AJAX - Oriented</h1>
<div>
Country:
<select id="country" ng-model="country" ng-options="country for country in countries">
<option value=''>Select</option>
</select>
</div>
<div>
City: <select id="city" ng-disabled="!cities" ng-model="city"><option value='' ng-repeat="item in cities" ng-disabled="item.disabled">{{item.name}}</option></select>
</div>
<div>
Suburb: <select id="suburb" ng-disabled="!suburbs" ng-model="suburb" ng-options="suburb for suburb in suburbs"><option value='' ng-disabled="item.disabled" ></option></select>
</div>
</div>
Your Angular
function AjaxCtrl($scope) {
$scope.countries = ['usa', 'canada', 'mexico', 'france'];
$scope.$watch('country', function(newVal) {
if (newVal)
$scope.cities = [
{ id: 1, name: '11111'},
{ id: 2, name: '22222', disabled: true },
{ id: 3, name: '33333', disabled: true }
]
});
$scope.$watch('city', function(newVal) {
if (newVal) $scope.suburbs = ['SOMA', 'Richmond', 'Sunset'];
});
}
function AjaxCtrl($scope) {
$scope.countries = ['usa', 'canada', 'mexico', 'france'];
$scope.$watch('country', function(newVal) {
if (newVal)
$scope.cities = [
{ id: 1, name: '11111'},
{ id: 2, name: '22222', disabled: true },
{ id: 3, name: '33333', disabled: true }
]
});
$scope.$watch('city', function(newVal) {
if (newVal) $scope.suburbs = ['SOMA', 'Richmond', 'Sunset'];
});
}
<link href="http://fiddle.jshell.net/css/normalize.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<div ng-controller="AjaxCtrl" class="ng-scope">
<h1>AJAX - Oriented</h1>
<div>
Country:
<select id="country" ng-model="country" ng-options="country for country in countries" class="ng-valid ng-dirty"><option value="" class="">Select</option><option value="0">usa</option><option value="1">canada</option><option value="2">mexico</option><option value="3">france</option></select>
</div>
<div>
City: <select id="city" ng-disabled="!cities" ng-model="city" class="ng-valid ng-dirty"><!-- ngRepeat: item in cities --><option value="" ng-repeat="item in cities" ng-disabled="item.disabled" class="ng-scope ng-binding">11111</option><option value="" ng-repeat="item in cities" ng-disabled="item.disabled" class="ng-scope ng-binding" disabled="disabled">22222</option><option value="" ng-repeat="item in cities" ng-disabled="item.disabled" class="ng-scope ng-binding" disabled="disabled">33333</option></select>
</div>
<div>
Suburb: <select id="suburb" ng-disabled="!suburbs" ng-model="suburb" ng-options="suburb for suburb in suburbs" class="ng-pristine ng-valid" disabled="disabled"><option value="" ng-disabled="item.disabled" class=""></option></select>
</div>
</div>
Reference

Categories

Resources