ng-change sends different values on chosen select - html

Dears, I am using a chosen select drop down list in select tag, and I added an ng-change tag to bind it to a function. Also I made a console.log to monitor the sent key. I found that when page load and select one item from the list it works good and sends the correct key. BUT when I select the same item it sends the key of the next item in the list. any help how to fix it
HTML
<div class="form-group">
<select ng-change="GetUsersList(j)" data-placeholder="Choose a Job"
ng-model="j" id="chosenValueID" class="chosen-select"
tabindex="1"
ng-options="j.JobKey as j.JobDesc for j in jobs">
</select>
<!--<select ng-change="GetUsersList(job)" data-placeholder="Choose a Job" ng-model="job" id="chosenValueID" class="chosen-select" tabindex="2">
<option ng-repeat="j in jobs track by $index" value="{{j.JobKey}}">{{j.JobDesc}}</option>
</select>-->
</div>
Angularjs
$scope.GetUsersList = function (job) {
//var jobkey1 = $("#chosenValueID").chosen().val();
//$scope.jobkey2 = jobkey1.substring(7);
console.log(job);
$scope.ShowLoading('slow');
FieldsSecuritySrv.GetUsersList("FieldsSecurity/GetUsersList?hospid=" + $scope.hospitalid + '&jobkey=' + job).then(function (response) {
$scope.UsersList = (response.data);
GetFieldsList();
GetCategriesList();
GetPatientSheets();
$scope.HideLoading('slow');
})
}
Thanks in Advance

No idea how you can bind jobs but can try ...
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.count = 0;
$scope.jobs=[
{JobKey : "1", JobDesc : "IT"},
{JobKey : "2", JobDesc : "Sales"},
{JobKey : "3", JobDesc : "Marketing"}
];
$scope.GetUsersList = function(job){
alert(job);
}
}]);
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<div class="form-group">
<select ng-change="GetUsersList(j)" data-placeholder="Choose a Job" ng-model="j" id="chosenValueID" class="chosen-select" tabindex="1" ng-options="j.JobKey as j.JobDesc for j in jobs"> </select>
</div>
</div>
</body>
</html>

your j variable in HTML is somehow messy, it is indexed for ng-repeat and used as ng-modal as well, so $scope.j is also created :(
<select ng-change="GetUsersList()" data-placeholder="Choose a Job" ng-model="selectedJob" id="chosenValueID" class="chosen-select"
tabindex="1" ng-options="j.JobDesc for j in jobs"></select>
In angular:
//initialize the way u like
$scope.selectedJob = $scope.Jobs[0];
$scope.GetUsersList = function () {
//var jobkey1 = $("#chosenValueID").chosen().val();
//$scope.jobkey2 = jobkey1.substring(7);
console.log($scope.selectedJob.jobKey);
$scope.ShowLoading('slow');
FieldsSecuritySrv.GetUsersList("FieldsSecurity/GetUsersList?hospid=" + $scope.hospitalid + '&jobkey=' + $scope.selectedJob.jobKey).then(function (response) {
$scope.UsersList = (response.data);
GetFieldsList();
GetCategriesList();
GetPatientSheets();
$scope.HideLoading('slow');
})
}

Related

Display label displayed in options as the title of select

How to show option.Brand.Name as the title of the select field without using java script and changing the ng-model?
<select ng-model="detail.BrandId" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
AngularJS and select-options
Try using ng-options AngularJS ngOptions directive within select element itself. Then you don't need to add each option element yourself using ng-repeat.
Clarification
The title-attribute belongs to the select-element and will show if you hover over the select. You would like the title to reveal the current selected option? Did I understand you correctly?
How to show option.Brand.Name as the title of the select field
Curious, where this detail.ProductId comes from? Is the brand preselected by product-id (see your code)?
ng-selected="option.Id === detail.ProductId"
Solution space
Your requirements/restrictions are:
without using JavaScript (maybe because you can't change the sources)
without changing the ng-model (because you need there only the BrandId for some database-reasons)
So since the title of the select-element has no access to the options inside, the only way to set it is depending on the current selection, i.e. your detail.BrandId. So the title can only set dynamically (depending on the current selection) by using standard-angularJS means, as:
{{ expression }} expressions
{{ expression | filter }} array-filter
Expected behavior
The only scope-variable changed by selecting is specified within select's ng-model as detail.BrandId. This will be set when user selects an option to its property BrandId. When user selects between options they will be visible with ther BrandName as label. After selection this BrandName (label of the option) should be shown as title of the entire select element.
So we need to get from detail.BrandId (selected ng-model) to related options BrandName (as this should show as title).
Possible Solution
Only way is to use standard angular expressions/filters/array-indexing to get the whole option by the selected detail.BrandId (ng-model)
Then we can lookup the option.BrandName by this equation after selected detail.BrandId === option.BrandId
var app = angular.module('app', []);
app.controller('mainCtrl', function($scope){
$scope.products = [
{Id: 0, name: 'Watson', brandId: 1, brandName:"IBM"},
{Id: 1, name: 'DB2', brandId: 1, brandName:"IBM"},
{Id: 2, name: 'Windows', brandId: 2, brandName: "Microsoft"},
{Id: 3, name: 'Office', brandId: 2, brandName: "Microsoft"}
];
$scope.detail = { ProductId: 3, BrandId: null };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body data-ng-app="app" data-ng-controller="mainCtrl">
<table border="1">
<tr>
<th>Product Id</th><th>Product Name</th><th>Choose Brand</th><th>Brand Id</th>
</tr>
<tr>
<td>{{detail.ProductId}}</td>
<td>{{ (products | filter: {Id: detail.ProductId})[0].name }}</td>
<td>
<select class="form-control"
ng-model="detail.BrandId"
ng-init="detail.BrandId = (products | filter: {Id: detail.ProductId})[0].brandId"
ng-options="o.brandId as ('['+ o.Id +'] '+ o.name +' : '+ o.brandName +' ('+ o.brandId +')') for o in products"
title="{{ (products | filter: {brandId: detail.BrandId})[0].brandName}}"
>
<!-- default option when not preset by detail.ProductId-->
<option value="">-- please choose brand --</option>
</select>
</td>
<td>{{detail.BrandId}}</td>
</tr>
</table>
<hr/>
<p>Product is predefined. So the brand is pre-selected by product. BUT: after brand is selected, the product-details do NOT change!</p>
Selected <strong>detail</strong>:
<pre ng-model="selected">{{detail | json}}</pre>
</body>
</html>
See also
For using ng-options, see also plunkr example.
You can register the selected option object in the ng-repeat parent scope by using as alias-expression provided by ng-repeat.
In your case you just need to do something like that:
<select ng-model="detail.BrandId"
title="{{options | selectedProductFilter : detail.ProductId}}"
class="form-control"
disabled>
<option ng-repeat="option in mainCtrl.products as options"
ng-selected="option.Id === detail.ProductId"
ng-value="option.BrandId">
{{option.Brand.Name}}
</option>
</select>
The options object will be available in your controller closure and you can display the title by using a custom filter.
angular.module("app").filter('selectedProductFilter',
function () {
return function (input, id) {
if (!input) return "";
let occurence = input.filter(function (x) {
return x.Id == id;
});
return occurence.length > 0 ? occurence[0].Brand.Name: "";
}
}
);
you need to do ng-change event in your select and call function in it that change the value of label text to the select value name. something like below
In Html
ng-change="changedValue(detail.BrandId)"
In JS
$scope.changedValue = function(item) {
//change label name here
}
fill ng-model by "option" not "option.BrandId"
then you can set title like this :
mainCtrl.products['ng-model-name'].Brand.Name
Here's how you could achive this:
(function () {
"use strict";
const app = angular.module("app", []);
app.controller("app.AppCtrl", $scope => {
$scope.selectedOption = null;
$scope.optionList = [{_id: 1, label: 'Option 1'}, {_id: 2, label: 'Option 2'}];
});
})();
body {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="app.AppCtrl">
<select title="{{selectedOption.label}}" class="form-control" ng-model="selectedOption">
<option ng-repeat="option in optionList" ng-value="option"> {{option.label}}</option>
</select>
</div>
Try using ng-init,
add ng-init to your select tag and put your object index value you want to be selected by default.
e.g.
Your code
<select ng-model="detail.BrandId" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
adding following code (Suppose I want index 0 by index):
ng-init="detail.BrandId = option[0].Brand.Name"
It will look like this :
<select ng-model="detail.BrandId" ng-init="detail.BrandId = option[0].Brand.Name" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
or Check these thread's
how to use ng-option to set default value of select element
How to set default value in ng-options

How to change select tags value when element is deleted from array?

I have select tag which takes values from array like this
<select class="groupForArchive" ng-model="selected.country">
<option ng-selected= "{{country == selected.country}}" ng-repeat="country in countrynList" value={{country}}> {{ country.name }} </option>
</select>
when I am deleting element from array(countryList) I am setting new value to this tag like this $scope.selected.country = newValue, but in select box I am getting free space like in this pictures.
before delete country from list
after delete country from list
and when I am taking select tag's ng-model I am getting correct object but I can not see it in my select box and I don't know which item is selected.
P.S newValue is array's another item(item from countrynList)
How can I fix it ?
Update AngularJS library to latest version and make changes, presented below:
angular.module('app', []).controller('ctrl', function($scope){
$scope.countrynList = [
{name:'USA'}, {name:'Spain'}, {name:'France'}, {name:'Germany'}
]
$scope.selected = {country: $scope.countrynList[0]};
$scope.Delete = function(){
var index = $scope.countrynList.indexOf($scope.selected.country);
$scope.countrynList.splice(index, 1);
$scope.selected.country = $scope.countrynList[0];
}
})
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<div ng-app='app' ng-controller='ctrl'>
<select class="groupForArchive" ng-model="selected.country">
<option ng-repeat="country in countrynList" ng-value='country'>
{{country.name}}
</option>
</select>
{{selected.country}}
<br>
<input type='button' ng-click='Delete()' value='Delete First'/>
</div>

Showing previously selected items in drop down menu

Using angular and angular-xeditable I have a drop down menu with a number of options from which to select in the 'amenities' array.
Once I save the selections from the drop down and saved them, I want to make it possible for the user to come back to the page and edit previously selected items.
HTML:
<select multiple class="w-select am-dropdown" size="12" data-ng-model="Amenities"
data-ng-options="amenity.amenity for amenity in amenities" required=""></select>
JS:
$scope.amenities = [{amenity: coffee}, {amenity: beer}, {amenity: parking}];
$scope.Amenities = [];
$scope.selectedAmenities = [coffee, beer];//these are amenities saved in the
database that I want to be able to show as selected using the editable form
Have a case as same as this
Add $scope.$watch to put selected value to $scope.selectedValues as below
$scope.$watch('selectedAmenities ', function (nowSelected) {
$scope.selectedValues = [];
if (!nowSelected) {
return;
}
angular.forEach(nowSelected, function (val) {
$scope.selectedValues.push(val.amenity.toString());
});
});
And then use it like below:
select multiple ng-model="selectedValues" class="w-select am-dropdown" size="12" >
<option ng-repeat="amenity in amenities" value="{{amenity.amenity}}" ng-selected="{{selectedValues.indexOf(amenity.amenity)!=-1}}">{{amenity.amenity}}</option>
</select>
Full code at Plunker
Hope it helps you.
do u mean this?
var m = angular.module('m', []).controller('c', ['$scope',
function($scope) {
$scope.avilibleValues = ['a1', 'a2', 'a3', 'a4', 'a5'];
$scope.selected = [];
$scope.last = 'a1';
$scope.selecting = 'a1';
$scope.select = function(it) {
console.log('select:' + it);
$scope.selecting = it;
};
$scope.change = function() {
console.log($scope.last);
$scope.last && $scope.selected.push($scope.last);
$scope.last = $scope.selecting;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="script.js"></script>
<div ng-app="m">
<div ng-controller="c">
<div class="row">
<label>seleted:</label>
<div>
<p ng-repeat="it in selected">
<a ng-click="select(it)">{{it}}</a>
</p>
<div>
</div>
<div class="row">
<label>selet</label>
<select ng-model="selecting" ng-options=" i for i in avilibleValues" ng-change="change()"></select>
</div>
</div>
</div>
<p>
selecting:{{selecting}}
<p>
selected:{{selected}}
<p>
last:{{last}}
<p>
</div>
</div>

Cascading list using custom directive of Angular JS while using json as input

I am trying to implement a custom directive using angular js's custom directive but first drop-down goes unselected and it gives me error saying "Error: 10 $digest() iteration reached. Aborting!
Watcher fired in the last 5 iterations:
index.html goes here -
<!doctype html>
<meta charset="utf-8">
<html>
<head>
<title>Adnan Try</title>
<script type="text/javascript" src="../js/1.0.7/angular.min.js"></script>
<script type="text/javascript" src="cascading.js"></script>
</head>
<body>
<div ng-app="cascading">
<div ng-controller="CascadingCtrl">
<cascading countries = "{
'India': {
'Maharashtra': ['Pune', 'Mumbai', 'Nagpur', 'Akola'],
'Madhya Pradesh': ['Indore', 'Bhopal', 'Jabalpur'],
'Rajasthan': ['Jaipur', 'Ajmer', 'Jodhpur']
},
'USA': {
'Alabama': ['Montgomery', 'Birmingham'],
'California': ['Sacramento', 'Fremont'],
'Illinois': ['Springfield', 'Chicago']
},
'Australia': {
'New South Wales': ['Sydney'],
'Victoria': ['Melbourne']
}
}"
></cascading>
</div>
</div>
</body>
</html>
cascading.js file is
angular.module('cascading', [])
.controller('CascadingCtrl', ['$scope', function($scope) {
}])
.directive('cascading', function() {
return {
restrict : "E",
scope : {
countries : '='
},
templateUrl: 'cascading.html',
link: function($scope, $element, $attribute) {
}
};
});
and cascading.html is here
<div>
Country:
<select id="country" ng-model="states" ng-options="country for (country, states) in countries">
<option value=''>Select</option>
</select>
</div>
<div>
States: <select id="state" ng-disabled="!states" ng-model="cities" ng-options="state for (state,city) in states">
<option value=''>Select</option></select>
</div>
<div>
City: <select id="city" ng-disabled="!cities" ng-model="city" ng-options="city for city in cities">
<option value=''>Select</option></select>
</div>
My hunch is i m doing something wrong in cascading.html that leaves angular js in clue less mode about two way binding.
EDIT
plnkr link is - http://plnkr.co/edit/osqXgK6CB1zpcMPfHTO3?p=preview
I found the problem.. Just used recent AngularJS and it seems everything is just working.. I used https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js and everything is just working.
PS:
Thanks #JB Nizet for your comment about.

Why are my inputs not resetting?

The below code generates several forms depending on data returned from the server. Everything generates fine, but after clicking on an AnswerOpenQuestion button the input does not clear/reset. What's going on here?
angularJs code:
var availableInterviewController = function($scope, $http) {
// define initial model
$scope.interviews = [];
// retrieve available interviews
$http.get('/api/UserInterviewsApi/AvailableInterviews')
.success(function(data) {
// update interviews
$scope.interviews = [];
$scope.interviews = data;
});
// define open question answer selection
$scope.Answer = "";
// define multiple choice selection
$scope.selectedChoice = "";
// define answer open question button
$scope.AnswerOpenQuestion = function() {
$scope.Answer = ans;
alert(q.Question + ' and ' + $scope.Answer);
$scope.Answer = ''; // <---This is not clearing/resetting the HTML form inputs
};
// define answer multiple choice button
$scope.AnswerMultipleChoice = function() {
//
};
};
// assign the new controller to the main angular app
myAngApp.controller('availableInterviewCtrl', availableInterviewController);
Html code:
<form class="form-group" ng-repeat="q in inter.Questions">
<fieldset style="display: inline-block;">
<legend>Question {{$index + 1}}</legend>
<!--Open Ended-->
<div class="form-group" ng-show="q.MultipleChoices.length === 0">
<label for="{{'quest-' + $index}}">
<strong class="text-info">{{q.Question}}</strong><br />
</label>
<input name="openQuestion" id="{{'quest-' + $index}}" type="text"
class="form-control" ng-model="Answer" />
<button ng-click="AnswerOpenQuestion()">Answer</button><br />
<span class="text-info">
asked by {{q.AskedByUserName ==
'Administrator' ? 'staff' : q.AskedByUserName}}
</span>
</div>
<!--Multiple Choice Question-->
<div class="form-group" ng-show="q.MultipleChoices.length > 0">
<label for="{{'quest-' + $index}}">
<strong class="text-info">{{q.Question}}</strong>
</label>
<div>
Select an answer:
<label ng-repeat="x in q.MultipleChoices">
<input name="currentChoice" type="radio" value="{{x.Id}}"
ng-model="selectedChoice" />
{{x.Choice}}
</label>
<button ng-click="AnswerMultipleChoice()">Answer</button><br />
<span class="text-info">
asked by {{q.AskedByUserName ==
'Administrator' ? 'staff' : q.AskedByUserName}}
</span>
</div>
</div>
</fieldset>
</form>
UPDATE - Solution
AngularJs:
// define open question answer selection
$scope.OpenAnswer = { Answer: '' };
// define answer open question button
$scope.AnswerOpenQuestion = function (q, ans) {
$scope.OpenAnswer.Answer = ans;
alert(q.Question + ' and ' + $scope.OpenAnswer.Answer);
// clear the input
$scope.OpenAnswer.Answer = '';
};
Html:
<input id="{{'quest-' + $index}}" type="text"
class="form-control" ng-model="OpenAnswer.Answer" />
Don't use the scope as a model instead make an object that wraps the data model and assign it to a property of the scope.
$scope.myModel = {Answer:''}
Also don't use value in most cases ngmodel is all you need for two way binding.
In js strings are immutable so the original reference is not being updated instead a new string is being made, the digest cycle won't see this as a change to the original string.