Showing values when you know the key in AngularJS - arrays

I have the variable:
$scope.rolesData = [{id : '1', name : 'user'}, {id : '2', name : 'superuser'},{id : '3', name : 'admin'}];
And I got from a DB an user object with integer value, which tells me what is the role. It is from 1 to 3. user.userRole is 1,2 or 3.
$scope.users = adminUserSvc.query(); //From DB
Everything is workin fine in select:
<tr ng-repeat="user in users">
...
<select class="form-control" ng-model="user.userRole" ng-options="role.id as role.name for role in rolesData">
</select>
But I wonder how I can show the same inside the {{}}? If I know that user.userRole is giving me id 1, how the heck I'll get the value of name?
This is inside the ngRepeat:
<div ng-hide="editingUsers[user.userId]">{{rolesDataSOMETHING??}}</div>

Ok you can use this:
{{(rolesData | filter:{id:user.userRole})[0].name}}
At first it filters the rolesData Object - then gets the first object (it should only be one because of the filter) with [0].
Old Answer (to old question):
You just need to save the right 'thing' in your model by changing your ng-options!
ng-options="role as role.name for role in rolesData"
This will save the whole role object {id : '1', name : 'user'} in your user.userRole model, to output the name just use {{user.userRole.name}}
There is no need for ngRepeat here.

You could use lodash (http://lodash.com) to find the element you are looking for. You'd probably want to put that in a function on your controller. Something like
$scope.getName = function(id) {
var i = _.findIndex($scope.rolesData, { id: id });
return $scope.rolesData[i].name;
}
And then in your template, you could reference this in the brackets like:
<div ng-hide="edingUsers[user.userId]">{{getName(user.userRole)}}

Related

how to make dropdown select a certain value from getting the id from the database?

The code below show a dropdown list from using ng-repeat. When I edit this entity, I have to make them show a certain value selected already than just showing a whole list. I know that I can put selected keyword when I want to select a certain value.
Then what if I used ng-repeat to populate a dropdown? How can I make a dropdown choose a certain value using the id?
<div ng-if="field.name=='ClienteleId'" class="input-group inputFill">
<select ng-disabled="defaultSaveButtons[$index]" class="form-control inputFill2"
ng-model="field.value" ng-options="clientele.id as clientele.name for clientele in dropdown.clienteleOptions | orderBy:'name' track by clientele.id"></select>
/div>
To set the value of a <select> in AngularJS, you need to change the variable that is set as its ng-model to one of the values in your options.
In your case, you have field.value as your ng-model, and your options use the name attribute as their label and the id attribute as their value. To have one of the items in dropdown.clienteleOptions selected by default, you need to set field.value to the id attribute of the corresponding entry in dropdown.clienteleOptions.
Imagine your options and fields look like this:
$scope.clienteleOptions = [
{id: 1, name: 'test 1'},
{id: 2, name: 'test 2'}
];
$scope.fields = [
{name: 'ClienteleId', value: null}
// ...
];
In your controller somewhere, you would have something like this to have test 2 selected:
$scope.fields[0].value = 2;
Or to make it more dynamic:
$scope.fields.forEach(function (field) {
if (field.name === 'ClienteleId') {
field.value = 2;
}
});

Update Angular dropdown after insert and select new value

I'm fairly new to Angular and was wondering how I can update a dropdown after doing an insert and have the new value selected?
I tried the following:
<select class="form-control" ng-model="selectedCompany" ng-change="GetCompany()"
ng-options="company.key as company.value for company in CompanyList">
<option value="">Select a Company</option>
</select>
This populates a list of companies when the page 1st loads and the inserted data is returned to scope + it's id.
To add the new value without refreshing the page, I'm trying the following non-working (almost) code:
var key = $scope.company.id;
var value = $scope.company.name;
$scope.CompanyList.push({ key: value });
$scope.selectedCompany = $scope.company.id;
This seems to add a value to the dropdown, but it's showing up blank. It's also not selecting the blank value (which should be the new company name), any help would be appreciated.
It seems that when you create the new company object, you need to assign the value property which is the display name.
Here's a code snippet:
angular.module("myApp", [])
.controller("testCtrl", function() {
this.companyList = [{
key: 1,
value: "Company A"
}];
var ctrl = this;
this.addCompany = function() {
ctrl.companyList.push({key:2, value:"Company B"});
ctrl.selectedCompany = 2;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="testCtrl as ctrl">
<select class="form-control"
ng-model="ctrl.selectedCompany"
ng-options="company.key as company.value for company in ctrl.companyList">
<option value="" disabled>Select a Company</option>
</select>
<button ng-click="ctrl.addCompany()">
Add company B and select it
</button>
</div>
Ok, so what do we have here?
You're creating your options with the ngOptions directive like this: ng-options="company.key as company.value for company in CompanyList"
That mean that the array $scope.CompanyList must have objects with a key property that will be set to the option value attribute, and a value that will be the option display value (Or label, if you prefer to call it that way).
What you were doing wrong: You added an object with only one property named key and set its value with the value variable: $scope.CompanyList.push({ key: value });
How should you fix it: You need to append object(s) with a key and a value like so: $scope.CompanyList.push({ key: key, value: value });
The following line push an object, which has a property name "key" set to value:
$scope.CompanyList.push({ key: value });
The result will be:
{'key': $scope.company.name}
You may change it to:
$scope.CompanyList.push({key: key, value: value});
Which will result in:
{ 'key': $scope.company.id, 'value': $scope.company.name }

How to run multiple successive select buttons in AngularJS

I facing an issue with having multiple selects in angularJS where each one of them is linked to the previous one and the value depended on the previous item selected which looks like could be done easily by angular but I am having a hard time figuring out how do I make the index of one select be passed to another select and at the same time making it unresponsive until some value is selected.
I also created a fiddle for the same for people to fiddle around with it.
Here is the concerned HTML
<div ng-app="myApp">
<div ng-controller="testController">
<select ng-model="carBrand" name="carBrand" required ng-options=" brand for brand in brands"></select>
<select ng-model="carModel" name="carModel" required ng-options="model.name for model in cars[0]"></select>
<!--I want the car brand(cars[0]) to be dynamic here. It should be prefreberably blacked out or uneditable until a Car brand is selected and once that particular brand is selected all the models pertaining to that brand only should be displayed in the ajoining select button-->
</div>
</div>
and an example app.js. Find the complete one at the fiddle
var app = angular.module('myApp', []);
app.controller("testController", function($scope) {
$scope.brands = ['Ford', 'Honda', 'Hyundai', 'Mahindra',
'Maruti Suzuki', 'Nissan', 'Renault', 'Skoda', 'Tata', 'Toyota', 'Volksvagen'
];
$scope.carBrand = $scope.brands[0];
$scope.cars = [];
/*These cars[0] and cars[1] are static declared but could well be called from a REST API endpoint in angular. For simplicity lets say they are already present. */
$scope.cars[0] = $scope.cars[0] = [{
name: "Figo",
capacity: 45
}, {
name: "Ecosport",
capacity: 52
}, {
name: "Fiesta",
capacity: 45
}, {
name: "Endeavour",
capacity: 71
}];
});
How do I solve the issue of getting an index from one select and passing it to the other to make this work and probably an additional perk would be to make it unresponsive in case no brand is selected.
Try ng-change:
<select ng-model="carBrand" name="carBrand" required ng-options=" brand for brand in brands"
ng-change="selectedCar(carBrand)"></select>
This returns the index of the selected brand:
$scope.selectedCar = function(brand) {
$scope.carIndex = $scope.brands.indexOf(brand);
};
Use it with the other dropdown as:
<select ng-model="carModel" name="carModel" required
ng-options="model.name for model in cars[carIndex]"></select>
Working Fiddle
When you select something from the first select, carBrand goes from undefined to the selected brand. You thus want the second select to be disabled if the carBrand is undefined (falsy):
<select ng-disabled="!carBrand" ...>
Then, you need to second select to contain the models associated to the selected brand (which is carBrand). So you need something like
<select ng-options="model.name for model in getModelsOfBrand(carBrand)" ...>
Now just implement this getModelsOfBrand(carBrand) function in the scope. It would be much easier if you had a better object model, like for example:
$scope.brands = [
{
name: 'Ford',
models: [
{
name: 'Figo',
capacity: 45
},
...
]
},
...
];
Then it would be as easy as
<select ng-options="model.name for model in carBrand.models" ...>

AngularJS: How to filter data in second select tag options based on first select tag's selected id

I am developing a mobile application where there is a view where there are two select tags first select tag consist of options of teams & in the second select tag there are forms associated with team Ids that user select in first select tag. I want to filter the data of second select tag as per the team Id of first select tag on ng-change event.
For the first select tag i have populated as follows:
<select ng-change="showForms(name.id)" ng-model="name" ng-options="f.name for f in devices track by f.id"></select>
my second select tag is this:
<select ><option ng-repeat="formEach in forms" id="{{formEach.Formid}}">{{formEach.Formname}}</option></select>
Here my concern is i dont want to show any forms that are present inside the forms array initially when user is about to select team. When user selects team, the forms with the selected teams id associated should be shown in the second select tag. How the filtering will be occur or is it on same page or through controller. I am familiar with PHP but task is in angular & am new to angularJS.
Thanks in advance for quick response.
Sample data is this:
devices = [
{id : X001, name :'Team 1', icon: 'ion-document-text', status : 'Owner', color : 'brown'},
{id : X002, name :'Team 2', icon: 'ion-document-text', status : 'Owner', color : 'yellow'},
{id : X003, name :'Team 3', icon: 'ion-document-text', status : 'Owner', color : 'black'}
];
forms data is this:
forms= [
{id : AS001, teamid: X001, formname :'Feam 1', icon: 'ion-document-text', status : 'Active'},
{id : AS002, teamid: X001, formname :'Feam 2', icon: 'ion-document-text', status : 'Draft'},
{id : AS003, teamid: X003, formname :'Feam 3', icon: 'ion-document-text', status : 'Draft'}
];
controller code is this: (controller logic is not written as am confused of populating the data as am filling the array at the time of navigation to this view)
$scope.showForms = function(teamId){
}
You can do this by simply following below trick. I've used the same in one of my project.
<select class="custom-select" ng-model="teamName" data-ng-options="f.id as f.name for f in devices" ng-change="updateTeamObject($index, teamName);">
<option value="">Select Team</option>
</select>
and in your second select, just use.
<select class="custom-select" ng-model="deviceForms" data-ng-options="o.id as o.formname for o in forms | filter:{teamid:teamName}">
<option value="">Your team data</option>
</select>
Fiddle
Try this:
<div ng-app>
<div ng-controller="TodoCtrl">
<select ng-change="showForms(name.id)" ng-model="name" ng-options="f.name for f in devices"></select>
<select ng-model="selected">
<option ng-repeat="formEach in forms| filter:{teamid:name.id }" id="{{formEach.id}}">{{formEach.formname}}</option>
</select>
</div>
</div>
Demo: http://jsfiddle.net/U3pVM/15890/
Explanation:
Important part is
ng-repeat="formEach in forms| filter:{teamid:name.id }"
Note how the filter is used. Specify the property (i.e. teamid in your case) where you want the filter to be applied. Since model name stores the selection, you can filter the next select dropdown by using name.id . For testing, just select the last option in the first select dropdown in the demo, the next dropdown will have the filtered results.
You can achieve it by pushing the items you want in the second select tag's array at the time of ng-change event of the first tag
In the ng-change function, push items into the array like this in the controller,
$scope.specifications = [];
angular.forEach($scope.allSpecifications, function(spec) {
if(spec.id == id) {
$scope.specifications.push(spec)
}
});
In Html use that array
<select ng-change="showSpec(car.id)" ng-init="car = carsList[0]" ng-model="car" ng-options="car.name for car in carsList"></select>
<select>
<option ng-repeat="primitive in specifications" id="{{primitive.id}}">{{primitive.name}}</option>
</select>
I have done one plunker with a sample JSON,
Working Plunker
Hope this helps!

How to sort object data source in ng-repeat in AngularJS?

Suppose I have the following users:
$scope.users = {
"2": {
email: 'john#gmail.com',
name: 'John'
},
"3": {
email: 'elisa#gmail.com',
name: 'Elisa'
}
}
I would like to create a <select> with the following options:
<option value="3">Elisa</option>
<option value="2">John</option>
In other words, users should be sorted by name.
I tried the following using the (key, value) in expression syntax, but it doesn't work:
<option ng-repeat="(user_id, user) in users | orderBy:'user.name'"
value="{{ user.id }}">
{{ user.name }}
</option>
Live example here.
What am I missing?
Please do not suggest solutions with ng-options as I use ui-select2 which is incompatible with ng-options.
While you would see this in the thread the author's answer references in a link, I thought it would be good to put up one of the mentioned workarounds up on SO:
It is true that this is technically not implemented, but there is an easy work around if you're willing to change your data model slightly: use a custom filter to generate an array of the object's properties (without replacement). If you add the key field to the objects ("id" in the above case), you should be able to get the behavior your looking for:
app.filter("toArray", function(){
return function(obj) {
var result = [];
angular.forEach(obj, function(val, key) {
result.push(val);
});
return result;
};
});
...
$scope.users = {
1: {name: "John", email: "john#gmail.com", id: 1},
2: {name: "Elisa", email: "elisa#gmail.com", id: 2}
};
Here's the ng-repeat directive that could be used:
<option value="{{user.id}}" ng-repeat="user in users | toArray | orderBy:'name'">{{user.name}}</option>
And here's the plunkr.
Notice that the orderBy filter takes name as its parameter and not user.name.
Unfortunately, adding the id property to your objects does create potential for mismatch with it's key in the containing object.
In the link you mentioned in your answer, there are also proposed solutions that create the id property in the user objects on the fly, but I feel like this approach is a little less messy (at the cost of introducing data replication).
OK, I found the answer:
It is not implemented yet :(
Adding to the accepted answer and seeing your data format, you should transform your data as
app.filter('myFilterUsers',function(){
return function(data)
{
var newRes = [];
angular.forEach(data,function(val,key){
val["id"] = key; //Add the ID in the JSON object as you need this as well.
newRes.push(val);
});
return newRes;
}
});

Resources