How to mark checkbox as checked in Angular controller - javascript

I have a form, which I'm using to enter new service requests, as well as display and edit those requests. A part of this form is a list of labeled check-boxes, representing all countries.
When the existing request is displayed using this form, I need to be able to compare each country check-box with a list of countries, which were initially selected, and marked each match as "checked". Another words, I need to restore the state of the check-box list to reflect what was checked originally. Should this type of logic handled in the controller by iterating over two nested loops (all countries Vs Selected countries), or is there a better way to do this using directives?
Here is my check-box list:
<div class="form-group">
<label for="selectbasic">What country is the data for</label>
<div>
<div style='height:100px;overflow-y:auto;border:solid 1px #aaa;'>
<div ng-repeat="item in countries">
<input type='checkbox' ng-model="item.checked" ng-change="checkit()" /> {{item.name}}
</div>
</div>
</div>
</div>
And here is the part of my controller in which I may be able to handle this:
function getServiceRequestById(Id) {
dataFactory.getServiceRequestById(Id)
.success(function (request) {
$scope.OID = request.OID;
$scope.Description = request.Description;
$scope.RequestorName = request.RequestorName;
$scope.RequestorBusinessUnit = request.RequestorBusinessUnit;
$scope.CustomerName = request.CustomerName;
$scope.CscContactPerson = request.CscContactPerson;
$scope.IsWbsCodeAvailable = request.IsWbsCodeAvailable;
$scope.SalesforceIdNumber = request.SalesforceIdNumber;
$scope.ProjectCtv = request.ProjectCtv;
$scope.RequestedCompletionDate = request.RequestedCompletionDate;
$scope.ToBeUsedForCloudMigration = request.ToBeUsedForCloudMigration;
$scope.ToBeUsedForDatacenterMove = request.ToBeUsedForDatacenterMove;
$scope.ToBeUsedForServerRefresh = request.toBeUsedForServerRefresh;
$scope.DataRequirements = request.DataRequirements;
$scope.DataProtectionRequirements = request.DataProtectionRequirements;
$scope.ProjectedDataAvailability = request.ProjectedDataAvailability;
$scope.DiscoveryLeadName = request.DiscoveryLeadName;
$scope.SelectedCountries = request.SelectedCountries;
$scope.ManualDiscovery = request.ManualDiscovery;
$scope.AutomatedDiscovery = request.AutomatedDiscovery;
$scope.DataLoadUsingMasterTemplate = request.DataLoadUsingMasterTemplate;
$scope.DataLoadUsingAutomatedInterface = request.DataLoadUsingAutomatedInterface;
$scope.DataLoaderRequiresSitizenship = request.DataLoaderRequiresSitizenship;
var list = [];
var countries = request.SelectedCountries.split(',');
console.log('number of countries: ' + countries.length);
console.log('countries[0]: ' + countries[0] + ' --- ' + countries[1]);
$scope.checkit = function () {
for (var p in $scope.countries) {
if ($scope.countries[p].checked) {
list.push($scope.countries[p].name);
console.log("selected country: " + $scope.countries[p].name + " " + $scope.ProjectedDataAvailability);
}
} return list;
}
console.log('EditServiceRequestCtrl request : ' + request);
})
.error(function (error) {
console.log('getServiceRequestById returned error ');
});
}

Try something like this:
function getServiceRequestById(Id) {
dataFactory.getServiceRequestById(Id)
.success(function (request) {
$scope.data = request;
$scope.selectecCountries = []; //make sure to clear selections
$scope.countries = request.SelectedCountries.split(',');
});
}
$scope.updateSelectedCountries = function() {
var list = [];
angular.forEach($scope.countries, function(country) {
if(country.selected) list.push(country);
});
$scope.selectedCountries = list;
};
Then in your view:
<div ng-repeat="country in countries track by $index">
<input type="checkbox" ng-model="country.selected" ng-change="updateSelectedCountries()"/>
</div>
<h4>Demo Output</h4>
<pre>{{ selectedCountries | json}}</pre>

It looks like you are getting a list of countries, where each item has a "checked" member.
I'm also assuming you want to display all countries, not just the checked ones.
If that's the case, it's pretty simple.
<div ng-repeat="item in countries">
<input type='checkbox' ng-model="item.checked" /> {{item.name}}
</div>
$scope.countries = [ {name: "USA", checked: true},
{name: "GBR", checked: false},
{name: "GER", checked: true}];
See a working plunker.

Related

How to set default selected text in ng-select or ng-options?

I am fairly new to AngularJS and I have been reading some answers here but nothing worked out. I have a json file from a controller that I display in a select. I want to set the selected value based on the text value.This is what I have so far.
HTML:
<div ng-app="userModule" ng-controller="userCtrl">
<div class="row">
<div class="col-md-6">
<label>User Name:</label> <br />
<select ng-model="users.selectedUser" class="form-control" ng-options="item.UserName as item.UserName for item in users.availableOptions"></select>
</div>
Controller:
<script>
var _$http;
var _$scope;
var oldUser = #Html.Raw(Json.Serialize(ViewData["UserName"]));
var oldRole = #Html.Raw(Json.Serialize(ViewData["RoleName"]));
angular.module('userModule', [])
.controller('userCtrl', xConstructor);
function xConstructor($scope, $http) {
_$http = $http;
_$scope = $scope;
$http.get("/RoleManagement/GetUserData").then(xReceive);
$http.get("/RoleManagement/GetRoleData").then(roleReceive);
_$scope.submit = function () {
//alert("Here:" + _$scope.selectedUser);
$http.get("/RoleManagement/PutUserRoleData?UserId=" + _$scope.selectedUser.UserId + "&RoleId=" + _$scope.selectedRole.RoleId).then(writeSuccess);
}
}
function xReceive(userObject) {
_$scope.users = {
availableOptions: userObject.data,
**selectedUser: { UserId: oldId, UserName: oldUser } //What to put here?**
};
alert(JSON.stringify(JSON.stringify(_$scope.users.selectedUser));
}
</script>
Or any other suggestions on how to do this?
The problem is you are not mapping the model to any element in the array you have.
Assuming you have the id of the user you want to select this is what you do:
function xReceive(userObject) {
_$scope.users = {
availableOptions: userObject.data,
selectedUser: null
};
let selectedUser;
for (let i = 0; i < userObject.data.length; i++) {
if (userObject.data[i].id === oldId) {
selectedUser = userObject.data[i];
break;
}
}
if (selectedUser) {
_$scope.users.selectedUser = selectedUser;
}
alert(JSON.stringify(JSON.stringify(_$scope.users.selectedUser));
}
Also note, you can do this to just select the first one:
_$scope.users.selectedUser = _$scope.users.availableOptions[0];

Checkboxes with array model in angularjs using asp.mvc

I am using Asp.MVC 5 for an application and I want to generate many checkboxes with different angularjs models, and I thought the best option is by using array model in angularjs. I tried the code below inside a foreach:
#{
int i = 0;
foreach (var selectedVesselViewModel in Model.SelectedVesselViewModels)
{
using (Html.BeginForm("SelectNotificaiton", "Admin", new { area = "DashBoard" }, FormMethod.Post, new { id = "filterVesselsForm_" + i}))
{
#Html.HiddenFor(item => selectedVesselViewModel.VesselId, new {ng_model= "SelectedVessels[" + i + "].VesselId" })
<li class="row">
<div class="col-md-10">
<a href="#" class="text-admin-area">
#selectedVesselViewModel.VesselName
</a>
</div>
<div class="col-md-2">
<div class="pull-right">
<div class="checkbox checkbox-inline">
#Html.CheckBoxFor(item => selectedVesselViewModel.Selected,
new {id = "SelectedVesselViewModels_"+i+"__Selected",
onchange ="document.getElementById('filterVesselsForm_"+i+"').submit()",
ng_model = "SelectedVessels[" + i + "].Selected"
})
<label for="SelectedVesselViewModels_#(i++)__Selected"></label>
</div>
</div>
</div>
</li>
}
}
}
i variable is an incrementing variable:
in the angularjs controller I have something like this:
(function (app) {
"use strict";
app.controller("DashboardCtrl", ['$scope',
function ($scope) {
function init() {
// $scope.SelectedVessels = [];
}
$scope.SelectedVessels = [];
init();
$scope.RefreshSideBarVessels = function() {
angular.forEach($scope.SelectedVessels, function (value, key) {
alert($scope.SelectedVessels[key].VesselId);
});
}
}]);
})(adminModule);
When I use angularjs foreach loop the $scope.SelectedVessels seems to be empty but I dont know why!
angular.forEach($scope.SelectedVessels, function (value, key) {
alert($scope.SelectedVessels[key].Selected);
});
Does anybody know where is the problem, why I cant access the inner properties of the $scope.SelectedVessels array and why it is empty ?
How you are adding values to your array ie. $scope.SelectedVessels is important
Please have a look at below example.
var values = {name: 'Raja', gender: 'male'};
var log = [];
angular.forEach(values, function(value, key) {
this.push(key + ': ' + value);
}, log);
expect(log).toEqual(['name: Raja', 'gender: male']);
Here is the solution to this problem:
I had to use ng-init to each checkbox to instantiate the ng-model.
#Html.CheckBoxFor(item => selectedVesselViewModel.Selected,
new {id = "SelectedVesselViewModels_"+i+"__Selected",
onchange ="document.getElementById('filterVesselsForm_"+i+"').submit()",
ng_model = "SelectedVessels[" + i + "].Selected",
ng_init = "SelectedVessels[" + i + "].Selected="+ selectedVesselViewModel.Selected.ToString().ToLower()
})
First off , its ng-model not ng_model (- vs _) but that could be typo.
Second, try this code
$scope.onChange = function (index, value) {
$scope.SelectedVessels[index] = value;
}
#Html.CheckBoxFor(item => selectedVesselViewModel.Selected,
SelectedVessels[i] = selectedVesselViewModel.Selected
new {id = "SelectedVesselViewModels_"+i+"__Selected",
onchange ="document.getElementById('filterVesselsForm_"+i+"').submit()",
ng-model = "SelectedVessels[" + i + "].Selected",
on-change="onChange(i,selectedVesselViewModel.Selected)
})

Sort a list of two different objects with one common property

I have two lists that are coming from an API that represent two different classes. I want to display the two lists according to their proprieties in one general list where the elements are sorted by their date.
I need to separate the two lists because the proprieties to display are different and they only share the Date.
I manage to display the two list separately but cannot merge the two... Does anyone have an idea on that? Thank you very much.
here is the .js and view:
.js:
function activityController($http) {
var vm = this;
vm.race= [];
vm.try= [];
vm.errorMessage = "";
vm.isBusy = true;
$http.get("/api/race")
.then(function (response) {
//Sucess
angular.copy(response.data, vm.race);
}, function (error) {
//Failure
vm.errorMessage = "Failed to load the data" + error;
})
$http.get("/api/try")
.then(function (response) {
//Sucess
angular.copy(response.data, vm.try);
}, function (error) {
//Failure
vm.errorMessage = "Failed to load the data" + error;
})
.finally(function () {
vm.isBusy = false;
});
}
View :
<div class="col-md-offset-7">
<div class="text-danger" ng-show="vm.errorMessage">{{ vm.errorMessage}}</div>
<wait-cursor ng-show="vm.isBusy"></wait-cursor>
<ul class="well" ng-repeat="activities in vm.race| orderBy: 'date':true">
<li> {{activities.title}}</li>
<li>Date : {{activities.date | date :'dd-MM-yyyy'}}</li>
<li>Temps : {{activities.time}}</li>
</ul>
<ul class="well" ng-repeat="activities in vm.try| orderBy: 'date':true">
<li> {{activities.person}}</li>
<li>Date : {{activities.date | date :'dd-MM-yyyy'}}</li>
<li>Temps : {{activities.type}}</li>
</ul>
The way I would do it is:
<ul class="well" ng-repeat="activities in vm.getRacesAndTrys()| orderBy: 'date':true">
<li> {{activities.title}}</li>
<li>Date : {{activities.date | date :'dd-MM-yyyy'}}</li>
<li>Temps : {{activities.time}}</li>
</ul>
With a function in your vm:
vm.getRacesAndTrys = function() {
var result = [];
for (var i = 0; i < vm.try.length; i++) {
var item = vm.try[i];
result.push({
title: item.person,
date: item.date,
time: item.type
});
}
for (var i = 0; i < vm.race.length; i++) {
result.push(vm.race[i]);
}
return result;
}
This will create a combined array and also convert all the try objects so that their fields match that of the race objects.

Filter ng-repeat with dropdown without duplicating the dropdown options

The same way, I can manually do filter: { category : 'Popular'} in ng-repeat, I'd like to be able to do the same thing with the dropdown.
I was able to make the basics work. I have two problems: I don't want the categories to duplicate themselves in the dropdown, I'd like to be able to see everything categorized "Popular" when I select "Popular" in the dropdown.
Here is my HTML:
<div ng-controller="SuperCtrl" class="row">
<ul class="small-12 medium-12 columns">
<select ng-model="find" ng-options="entry.category for entry in parsedEntries"><option value="">Select Category</option></select>.
<li ng-repeat="entry in parsedEntries | filter: find">
<strong>{{ entry.title }} </strong><br>
{{ entry.description }}
</li>
</ul></div>
Here is the controller:
app.controller('SuperCtrl', ['$scope', '$http', function($scope,$http) {
var url = 'https://spreadsheets.google.com/feeds/list/1lZWwacSVxTD_ciOsuNsrzeMTNAl0Dj8SOrbaMqPKM7U/od6/public/values?alt=json'
var parse = function(entry) {
var category = entry['gsx$category']['$t'];
var description = entry['gsx$description']['$t'];
var title = entry['gsx$title']['$t'];
return {
category: category,
description: description,
title: title
};
}
$http.get(url)
.success(function(response) {
var entries = response['feed']['entry'];
$scope.parsedEntries = [];
for (key in entries) {
var content = entries[key];
$scope.parsedEntries.push(parse(content));
}
});
}]);
Got it working as you want with :
<select ng-model="find" ng-options="entry.category as entry.category for entry in parsedEntries | unique: 'category'">
The unique filter is from angular-filter. It requires to add 'angular.filter' you to your modules dependencies:
var app = angular.module('myApp', ['angular.filter']);
See fiddle
NB: Not a problem by itself but I took the <select> element out of the <ul> one.
Just put unique categories into in a string array called categories, sort the array, and display it with ng-options:
<select ng-model="find" ng-options="category as category for category in categories"><option value="">Select Category</option></select>.
Append this to your code after your parse function, and delete the $http.get you had. This defines a contains function and builds the array at the same time the objects come back:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
};
$http.get(url)
.success(function(response) {
var entries = response['feed']['entry'];
$scope.parsedEntries = [];
$scope.categories = [];
for (key in entries) {
var content = entries[key];
var obj = parse(content);
$scope.parsedEntries.push(obj);
if (!contains($scope.categories, obj.category))
{
$scope.categories.push(obj.category);
}
}
$scope.categories.sort();
})

Using AngularJS to create an instant search by querying an array

This is going to be a rather longwinded question, so please bear with me...
I have an array of about 25-30 items. They are sorted through various filters such as brand, type, material, size, etc.. How can I go about building a searchable filter. All of the ones I've seen just include a filter:query | in their filters. However I can't get mine to query my existing array.
Here is what my array looks like, only going to show 1 item to keep size down..
$scope.products = [
{
src: 'images/img/image1.jpg',
name: 'XXX-1A',
brand: 'Brand A',
material: 'dry',
size: '00',
type: 'dry pipe',
color:'red'
}];
Function for filtering (only included 1 to save space):
$scope.brandIncludes = [];
$scope.includeBrand = function(brand) {
var i = $.inArray(brand, $scope.brandIncludes);
if (i > -1) {
$scope.brandIncludes.splice(i, 1);
} else {
$scope.brandIncludes.push(brand);
}
}
$scope.brandFilter = function(products) {
if ($scope.brandIncludes.length > 0) {
if ($.inArray(products.brand, $scope.brandIncludes) < 0)
return;
}
return true;
}
This is what I am using to filter from the HTML, I am using checkboxes to select each filter:
<div class="info" ng-repeat="p in products |
filter:brandFilter |
filter:materialFilter |
filter:typeFilter |
filter:styleFilter">
</div>
My search bar mark up:
<div class="filtering">
<div class="search-sect">
<input name="dbQuery" type="text" placeholder="Search pieces" class="search-input" ng-model="query"/>
</div>
One of the filter's mark up:
<input type="checkbox" ng-click="includeStyle('adaptor')"/>Adaptor<br>
Now that you have all the code, here are some of the things I've tried that don't seem to be running right:
My Attempt:
Search bar:
<input type="text" id="query" ng-model="query"/>
Filter:
<li ng-repeat="p in products | filter:query | orderBy: orderList">
I understand that to some experienced with angular, this is a relatively easy task, but I am just learning and can't seem to wrap my head around searching a query. It's probably a simple solution that I am overlooking. This is my first Angular app and I am trying to bite off more than I can chew in order to learn more.
I appreciate all responses, thanks in advance!
As per request: CodePen
The simple built-in angular filter is not smart enough to to work with your checkbox design, so try writing a custom filter. You will need to bind the checkboxes you mentioned to variables in your scope, e.g. brandFilterIsEnabled. See the tutorial for writing custom filters. Here is a working example.
var myApp = angular.module('myApp', []);
myApp.controller('ctrl', function ($scope) {
$scope.items = [{
name:'foo',
color:'red'
},{
name:'bar',
color:'blue'
},{
name:'baz',
color:'green'
}];
$scope.searchNames = true;
$scope.searchColors = true;
$scope.$watch('searchColors', function(){
$scope.searchKeys = [ $scope.searchNames ? 'name' : null, $scope.searchColors ? 'color' : null ];
});
$scope.$watch('searchNames', function(){
$scope.searchKeys = [ $scope.searchNames ? 'name' : null, $scope.searchColors ? 'color' : null ];
});
});
myApp.filter('advancedSearch', function($filter) {
return function(data, keys, query) {
results = [];
if( !query ){
return data;
} else {
angular.forEach( data, function( obj ){
var matched = false;
angular.forEach( keys, function( key ){
if( obj[key] ){
// match values using angular's built-in filter
if ($filter('filter')([obj[key]], query).length > 0){
// don't add objects to results twice if multiple
// keys have values that match query
if( !matched ) {
results.push(obj);
}
matched = true;
}
}
});
});
}
return results;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="myApp">
<div ng-controller="ctrl">
<input type='checkbox' ng-model='searchNames'>search names</input>
<input type='checkbox' ng-model='searchColors'>search colors</input>
<input type='text' ng-model='query'>search objects</input>
<ul>
<li ng-repeat="item in items | advancedSearch : searchKeys : query">
<span style="color:{{item.color}}">{{item.name}}</span>
</li>
</ul>
</div>
</html>

Categories