AngularJS multi-select using ng-repeat - javascript

I'm new to AngularJS and JavaScript. I've come up with a way to build a multi-select list, which is working. The ng-model associated with the dropdown is part of a "user" DTO object, specifically a member which contains an array of "groups" the user can belong to. The "master list" of possible groups are read from a database table using a webservice, put in an array and this is what's used to build the dropdown when the page is displayed.
Those elements in the list that are included in the "groups" field of the user object are displayed below the dropdown in a "preview" field. That's all working - if a user has two selected groups, they come up in that pre-field when the page is populated... but I don't understand why these groups are not highlighted in the dropdown. Sometimes they are...like sometimes when I refresh the page, but most of the time when the page is displayed and populated from the user information, these groups contained in the user are not highlighted in the dropdown.
Here's how the code is set up (again, I'm new to AngularJS/JavaScript and webservices so bear with me).
The HTML code is like this:
<div class="form-group">
<label for="Groups" class="col-sm-2 control-label">Group Memberships: </label>
<div class="col-sm-10">
<select name="userGroups" id="userGroups" ng-model="user.userGroups" multiple style="width: 300px;">
<option ng-repeat="group in approverGroups" value="{{group.name}}" selected >{{group.name}}</option>
</select>
<pre>{{user.userGroups.toString()}}</pre>
</div>
</div>
The JavaScript side looks like this. The "get" is used to read all possible groups from a table, and that populates the dropdown:
$http({
method : 'GET',
url : '/pkgAART/rs/ApproverGroupService/approvergroups',
data : {
applicationId : 3
}
}).success(function(result) {
// Create an array from the groups for use
// in the multi-select UI component for groups
var arr = [];
for (var i = 0; i < result.approvergroup.length; i++) {
var id = result.approvergroup[i].approverGroupId;
var value = result.approvergroup[i].name;
var pair = {id : id, name : value };
arr.push(pair);
}
$scope.approverGroups = arr;
});
Here's a screenshot of the page. This is how it looks:
So again, it works, and "SOMETIMES" when I pull up the page, the items listed in the lower <pre> box are actually highlighted in the dropdown, but not often. I don't understand how to ensure they come up highlighted. In the picture I manually clicked these elements. But if I refresh the page, sometimes they are and sometimes they are not.

I think I figured it out. Per Peter's suggestion I changed to ng-options for the dropdown, but modified the array that I use as my options to just use the name string. Here's the HTML
<div class="form-group">
<label for="Groups" class="col-sm-2 control-label">Group Memberships: </label>
<div class="col-sm-10">
<select name="userGroups"
id="userGroups"
ng-model="user.userGroups"
multiple="true"
style="width: 300px;"
ng-options="group for group in approverGroups">
</select>
<pre>{{user.userGroups.toString()}}</pre>
</div>
</div>
and the js file that builds up the array of strings looks like this:
$http({
method : 'GET',
url : '/pkgAART/rs/ApproverGroupService/approvergroups',
data : {
applicationId : 3
}
}).success(function(result) {
// create an array from the groups for use
// in the multi-select UI component for groups
var arr = [];
for (var i = 0; i < result.approvergroup.length; i++) {
var value = result.approvergroup[i].name;
arr.push(value);
}
$scope.approverGroups = arr;
});
It's now showing the multi-select list's items as selected if they are contained in "user.userGroups"
Mark

I think I figured it out.
First off, you should use ng-options in the select instead of ng-repeat on <option>. This makes it so the options are bound to the model of the select.
Check out this fiddle: http://jsfiddle.net/mcxqjngm/3/
Here is the relevant select html:
<select
name="userGroups"
id="userGroups"
ng-model="user.userGroups"
multiple="true"
style="width: 300px;"
ng-options="group.name for group in approverGroups track by group.id">
</select>
The button mimics an ajax call. I gotta run, but I can answer questions in a bit.

Related

Getting the selected string in the dropdown list in Angular

To begin with, I am an absolute beginner in front-end development, thus please excuse me if the question is too elementary.
The project I am working on, a drop-down list has been defined as:
<div ng-controller="FacetController">
<div class="spnlocationdrop-container" ng-hide="isservicelocal">
<select class="spnlocationdrop" ng-model="$parent.locationsearch" ng-options="location for location in locations | sortArray ">
<option value="">All Cities</option>
</select>
</div>
</div>
The list contains cities, out-of which the user has to select one. The value has to be stored, and sent to the backend via an AJAX call.
How do I get the selected value? Until now, I've been doing that using the document.getElementByID().value() function, but since the above list contains no ID, how do I get the value?
ng-model will have the value of the option selected.
Here's a simple working example: Plunker
In my example, data.singleSelect has the value you need so I'm able to output that to the view using {{ data.singleSelect }} though if I wanted to access it in my controller I would do var input = $scope.data.singleSelect and then pass that input variable to the backend via an AJAX call.

Angular Js- Is there any way to generate dynamically checkbox which are also preselected?

I have been wandering for two to three hours and I found chunks of relevant questions but my scenario just take a little curve. I have to generate a number of checkboxes which obviously would be generated through ng-repeat. How can I show the preselected values which I am getting from Api. Here is the kind of data I am receiving.
Pre-selected data
$scope.categoriess = [{"id":1,"name":"Garden Cleaning"},{"id":3,"name":"Home Cleaning"}].
and this is the data over which I am using ng-repeat.
ng-repeat data
$scope.categories = [{"id":1,"name":"Garden Cleaning"},{"id":2,"name":"Gutter Cleaning"},{"id":3,"name":"Home Cleaning"},{"id":4,"name":"Pool Cleaning"}
HTML
<div ng-repeat="cats in categories">
<input type="checkbox" ng-model="categoriess.id[cats.id]">
<label>{{cats.name}}</label>
</div>
Now how would i tell ng-repeat to check the preselected data, plus if I want to check few more boxes they should also be checked and I want them to store in $scope.categoriess. I have tried a number of solution either with ng-checked or by make a function call in ng-checked I got no expected results.
Why don't u format your data to have another property, something like
{"id":1,"name":"Garden Cleaning", "checked": true}
Such way, when u iterate through the data, you can check the checkbox
<div ng-repeat="cats in categories">
<input type="checkbox" ng-checked="cats.checked">
<label>{{cats.name}}</label>
</div>
I saw this but i did not know how it works god it saved my life. see this checklist-model. Its so simple , no need to use ng-checked or something dynamic , preselected and gets updated easily
[1]: http://jsfiddle.net/iem_usman/v3k6pwrj/1/
Change your html like this :
<div ng-repeat="cats in categories">
<input type="checkbox" ng-model="categoriess.id[cats.id]" ng-checked="isChecked(cats.id);">
<label>{{cats.name}}</label>
</div>
Add this function in your controller :
$scope.selectedCategoriess = [{"id":1,"name":"Garden Cleaning"},{"id":3,"name":"Home Cleaning"}].
$scope.isChecked = function(id){
for (var i = 0; i < $scope.selectedCategoriess.length; i++) {
if ($scope.selectedCategoriess[i].id == id) {
return true;
}
}
return false;
}
If id is available checked value will be "true".

AngularJS input select with integer value in ng-model stop working

I have a app written in C# .NET using WebApi and AngularJS.
At some points in my aplication I fill up a select tag with options using ENUMS, because since the values ​​are not in the database I don't feel like need to create a service that return the enums because I'm using razor pages so I can use the enums directly.
Everything was working fine until I updated the angular version to 1.4.7, Than this stop working, and I can't downgrade the angular version (for some enterprise reasons).
For example, I have this code
<div class="col-md-3 col-xs-12">
<label for="qualificacaoCobreJunta" class="col-xs-12 control-label">#IsiCTB.Internationalization.Res.Controls.label_cobre_junta<span class="obrigatorio">*</span></label>
<div class="col-xs-12">
<select class="form-control" id="qualificacao-cobre-junta" name="qualificacaoCobreJunta" ng-model="qualificacao.cobrejunta"
required>
<option value="" id="cobrejunta-0">#IsiCTB.Internationalization.Res.Controls.label_prompt_selecione</option>
<option id="optCobreJuntaCom" value="#IsiCTB.Entities.Enums.ComSem.Com.ToInt()">#IsiCTB.Entities.Enums.ComSem.Com.GetValueString()</option>
<option id="optCobreJuntaSem" value="#IsiCTB.Entities.Enums.ComSem.Sem.ToInt()">#IsiCTB.Entities.Enums.ComSem.Sem.GetValueString()</option>
<option id="optCobreJuntaAmbos" value="#IsiCTB.Entities.Enums.ComSem.Ambos.ToInt()">#IsiCTB.Entities.Enums.ComSem.Ambos.GetValueString()</option>
<option id="optCobreJuntaNA" value="#IsiCTB.Entities.Enums.ComSem.NA.ToInt()">#IsiCTB.Entities.Enums.ComSem.NA.GetValueString()</option>
</select>
<div ng-show="formQualificacaoSubmitted" class="error-form-validation">
<div ng-show="gerenciaQualificacoesSoldador.qualificacaoCobreJunta.$error.required">#IsiCTB.Internationalization.Res.Controls.label_obrigatorio</div>
</div>
</div>
</div>
Code getting data from WebApi.
QualificacaoService.get({ id: idQualificacao }, function (data) {
$scope.qualificacao = data;
});
And that return a JSON object with a bunch of attributes, like that:
{
id: 1,
cobrejunta: 2,
anotherEnumField: 1,
anotherEnumField2: 5,
anotherEnumField3: 2
....
}
If I have like qualificacao.cobrejunta = "2" (string) setting in the model, the select is pointing to right option, but if I have qualificacao.cobrejunta = 2 (integer) than nothing seems to work.
There's anyway to get this working again, or the only (best) solution is crete a service that will request a API, and this API will build the array and than return that for using ng-option?
Thank you guys.
This is discussed here.
All you have to do is to change your select as below
<select class="form-control" id="qualificacao-cobre-junta" name="qualificacaoCobreJunta" ng-model="qualificacao.cobrejunta" required
ng-options="entry.value as entry.label for entry in [{value : #IsiCTB.Entities.Enums.ComSem.Com.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Com.GetValueString()'}, {value: #IsiCTB.Entities.Enums.ComSem.Sem.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Sem.GetValueString()'}, {value: #IsiCTB.Entities.Enums.ComSem.Ambos.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Ambos.GetValueString()'}, {value:#IsiCTB.Entities.Enums.ComSem.NA.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.NA.GetValueString()'}]">
</select>
I think Angular behaviour has changed with the version 1.4.8. I had the same problem: I had a list of values into a combo (static values), and I assigned dynamically the value to select throught the controller. It wasn't a problem with version 1.3.8, but it's with 1.4.8 when the selected value remains blank. But I can show the value in the view, and it's correct.
The way to solve this for me was to translate that static values, to an object containing that values, and defining it al the begin of the controller (before assigning the value). It's strange to have to do it, but I didn't find another way to success.

Kendo Template source binding array creates double entries

I am using a Kendo template with an array to dynamically add rows to a form, however, when I push an item onto the array, it adds two rows, both bound to the same data object in the MVVM (so with two objects, there are four rows). I've run the page with a debugger; line in the template, and as suspected, it hits twice before it finishes.
And what's weirder is that it renders the rows in order, then in reverse order, so if I make a change on the first row, it then makes the same change to the last row (since they are bound to the same object in the array), etc.
HTML
Here is the HTML where the form resides (the observable object classInfo is already bound to the <form> tag, hence the reason it's missing from the data-bind):
<fieldset id="classWhen">
<p>
<!-- other form stuff -->
</p>
<div id="classDates" data-bind="source: classInfo.ClassDates" data-template="classDateTemplate"></div>
</fieldset>
Kendo Template
Here is the template which is a row that contains a dropdown list and two date pickers:
<script id='classDateTemplate' type='text/kendo-ui-template'>
<p>
<select class="classDateTypeDropdown">
<option><!-- TYPE 1 --></option>
<option><!-- TYPE 2 --></option>
<option><!-- TYPE 3 --></option>
<option><!-- TYPE 4 --></option>
</select>
<input class="classDatePicker" data-bind="value: DateStart" style="width: 125px;" /> to
<input class="classDatePicker" data-bind="value: DateStop" style="width: 125px;" />
</p>
</script>
Kendo Observable Object
Here is the Kendo Observable which has an array, which is formatted as such:
var classModel = new kendo.observable({
classInfo: {
//.....
ClassDates: [],
//.....
}
});
Javascript push Function
And an addDate() function which pushes a new item to the array:
function addDate() {
classModel.get("classInfo.ClassDates").push({
"ClassType": "Type 1",
"DateStart": null,
"DateStop": null
});
//change inputs to DatePickers
//change select to DropDownList
}
I have tried running it without creating the DropDownList and DatePickers, using the basic HTML elements, but with the same result. Any help would be greatly appreciated.
So, I'm not sure why this was happening (some research will need to be involved), but the cause of the problem was with my binding. Apparently the Kendo template does not like binding to object arrays that belong to other objects, as I have with classInfo.ClassDates.
I changed the bindings from:
kendo.bind($('#addClassWindow'), classModel);
<div data-bind="source:classInfo.ClassDates"data-template="classDateTemplate"></div>
to:
kendo.bind($('#addClassWindow'), classModel.classInfo);
<div data-bind="source:ClassDates"data-template="classDateTemplate"></div>
and now it works fine. For whatever reason.

How to select form input based on label inner HTML?

I have multiple forms that are dynamically created with different input names and id's. The only thing unique they will have is the inner HTML of the label. Is it possible to select the input via the label inner HTML with jQuery? Here is an example of one of my patient date of birth blocks, there are many and all unique except for innerHTML.
<div class="iphorm-element-spacer iphorm-element-spacer-text iphorm_1_8-element-spacer">
<label for="iphorm_081a9e2e6b9c83d70496906bb4671904150cf4b43c0cb1_8">events=Object { mouseover=[1], mouseout=[1]}handle=function()data=Object { InFieldLabels={...}}
Patient DOB
<span class="iphorm-required">*</span>
</label>
<div class="iphorm-input-wrap iphorm-input-wrap-text iphorm_1_8-input-wrap">
<input id="iphorm_081a9e2e6b9c83d70496906bb4671904150cf4b43c0cb1_8" class="iphorm-element-text iphorm_1_8" type="text" value="" name="iphorm_1_8">events=Object { focus=[1], blur=[1], keydown=[1], more...}handle=function()
</div>
<div class="iphorm-errors-wrap iphorm-hidden"> </div>
This is in a Wordpress Plugin and because we are building to allow employees to edit their sites (this is actually a Wordpress Network), we do not want to alter the plugin if possible.
Note that the label "for" and the input "id" share the same dynamic key, so this might be a way to maybe get the id, but wanted to see if there is a shorter way of doing this.
Here I cleaned up what is likely not used...
<div>
<label for="iphorm_081a9e2e6b9c83d70496906bb4671904150cf4b43c0cb1_8">
Patient DOB
<span class="iphorm-required">*</span>
</label>
<div>
<input id="iphorm_081a9e2e6b9c83d70496906bb4671904150cf4b43c0cb1_8">
</div>
You can use the contains selector to select the Patient DOB labels, then find the related input.
$('label:contains("Patient DOB")').parent('div').find('input');
This assumes that the label and input are wrapped in the same div and may not work if more than one pair is in the same div. At least the first part will get you the labels that contain Patient DOB, then you can adjust the later parts to find the correct input element.
For more help on jquery selectors, see the API.
Here is a fiddle demonstrating this.
var getForm = function(labelInnerHtml) {
var $labels = jQuery('label');
$labels.each(function() {
if (jQuery(this).html() == labelInnerHtml) {
var for_id = jQuery(this).attr('for');
return jQuery('#'+for_id);
}
});
return [];
};​​
The class iphorm_1_8 on the input is unique for each form element. So it's simple.
$('.iphorm_1_8');

Categories

Resources