when user open modal window i am calling rest service to get boolean flag that is data in below code, Now if that flag is true i want to disable option in ng-options where id is RA_ATTST_LANGUAGE. How can i disabled dropdown option based on below logic ?
main.html
<select name="adminNotificationTypeCode" class="form-control" ng-model="messageNotificationDTO.adminNotificationTypeCode" required id="adminNotificationTypeCode" ng-change="attestationCheck()" ng-options="adminDataSource.id as adminDataSource.text disable when adminDataSource.id == 'RA_ATTST_LANGUAGE' && disableRA_ATTST_LANGUAGE for adminDataSource in adminDataSource">
<option value="">Select...</option>
</select>
main.js
function getAttestationLanValidation (){
MessageAdminNotificationFactory.getAttestationLanValidation().then(function(response){
if(response){
$scope.disableRA_ATTST_LANGUAGE = response.data;
}
});
};
//Add new Notification
$scope.addMessageNotification = function() {
$scope.messageNotificationModal.open().center();
$scope.clearNotificationForm();
getAttestationLanValidation();
};
dropdown.json
[{
"uid": null,
"index": 0,
"selected": null,
"expanded": null,
"id": "RA_PLTFRM_NOTIF",
"text": "Platform Maintenance Notification",
"parentId": null,
"items": null
}, {
"uid": null,
"index": 0,
"selected": null,
"expanded": null,
"id": "RA_ATTST_LANGUAGE",
"text": "Attestation Language",
"parentId": null,
"items": null
}]
*Edited due to further explanation
try updating your ng-options attribute to this:
ng-options="adminDataSource.id as adminDataSource.text disable when adminDataSource.id == 'RA_ATTST_LANGUAGE' && disableRA_ATTST_LANGUAGE for adminDataSource in adminDataSource"
you will want to create a Boolean member to your scope that you set to true or false depending on the rest result.. I called it $scope.disableRA_ATTST_LANGUAGE
Plunker for demonstration
Assuming everything else is correct in your code, and that your service is making a single call per instance in your dropdown.json; If you only need to know if data is present and don't need to get the actual data content, a quick-and-dirty way is to just store the name in an array and check for presence of the id in that array using the ng-disabled directive. Your variable names were confusing, so I just genericized them and called the source array for your select options "items"
Your js needs something like this
// create an empty array when initializing
$scope.thatArrayOfIdsThatHaveData = [];
function getAttestationLanValidation() {
MessageAdminNotificationFactory.getAttestationLanValidation()
.then(function(response) {
var data = response.data;
console.log('attestation', data);
if (data) {
thatArrayOfIdsThatHaveData.push(id);
}
});
};
In your template something like this:
<select ng-model="messageNotificationDTO.adminNotificationTypeCode"
ng-change="attestationCheck()">
<option value="">Select...</option>
<option ng-repeat="item in items"
value="item.id"
ng-disabled="thatArrayOfIdsThatHaveData.indexOf(item.id)>=0">{{ item.label }}</option>
</select>
Related
A user object is available to the view which populates a form. One of the elements to display information is a drop-down. Two requests are made. One for the user information, and the other for a list of timezones. Both are resolved through a ui-router state like so:
.state('app.userprofile', {
url: '/userprofile',
component: 'user',
resolve: {
user: ['userService', function(userService) {
return userService.fetchUser();
}],
timezones: ['timezoneService', function(timezoneService){
return timezoneService.fetchUsaTimeZones();
}]
}
})
}]);
I have given a read of an article I found online after the select element failed to populate with the users timezone, but the select element still fails to display information.
Question
How do I populate the default select option with data from the user object but populate the options from the second response.
<label for="timezones">Time Zone</label>
<div>
<select name="timezones"
ng-init="userTimezone = $ctrl.user.business.timezone"
ng-change="userTimezone = userTimezone.abbr"
ng-model="userTimezone"
ng-options="item as item.abbr for item in $ctrl.timezones track by item.abbr" class="form-control">
<option value="">{{userTimezone}}</option>
</select>
<p>{{userTimezone}}</p>
</div>
//SECOND REQUEST FOR TIMEZONES
app.factory('timezoneService', ['$http', '$q', function($http, $q){
var factory = {};
factory.fetchUsaTimeZones = function() {
var deferred = $q.defer();
$http.get('../../p3sweb/assets/json/ustimezones.json')
.then(
function(response){
console.log(response.data.ustimezones)
deferred.resolve(response.data.ustimezones)
},
function(errResponse){
deferred.resolve(errResponse)
}
);
return deferred.promise;
}
return factory;
}])
{
"ustimezones": [
{
"value": "Hawaiian Standard Time",
"abbr": "HST",
"offset": -10,
"isdst": false,
"text": "(UTC-10:00) Hawaii",
"utc": [
"Etc/GMT+10",
"Pacific/Honolulu",
"Pacific/Johnston",
"Pacific/Rarotonga",
"Pacific/Tahiti"
]
},
{
"value": "Alaskan Standard Time",
"abbr": "AKDT",
"offset": -8,
"isdst": true,
"text": "(UTC-09:00) Alaska",
"utc": [
"America/Anchorage",
"America/Juneau",
"America/Nome",
"America/Sitka",
"America/Yakutat"
]
}
]
}
UPDATE
It was throwing an error when I had the value of ng-model as $ctrl.user.business.timezone so I have stored the it in a variable userTimezone through the ng-init directive. Updated the code
UPDATE 2
I have it semi-working. It updates all fields though it throws an inconsitent 405 error. Not going to lie, I'm in one of those 'how the hell is this working' situations.
<select name="timezones"
ng-init="userTimezone._abbr = {abbr: $ctrl.user.business.timezone}"
ng-change="$ctrl.user.business.timezone = userTimezone._abbr"
ng-model="userTimezone._abbr"
ng-options="zone.abbr as zone.text for zone in $ctrl.timezones track by zone.abbr" class="form-control">
<option value="">{{userTimezone._abbr}}</option>
</select>
<p>{{userTimezone._abbr}}</p>
You have complex objects as your options. Angular does equality comparison when checking the default value (which is set via the ng-model attribute), so with objects it's comparing object references (via the generated $$hashkey property). Because you have two different object references, once from the timezone list, once from the user, their hashkeys are different. Thus, they're treated as "not equal", so no default gets set.
If you extend your ng-options attribute to use track by, you can select a unique, primitive property where equality comparison makes more sense (such as the abbreviation). Angular will then use this property for equality/uniqueness comparison instead of the hashkey.
So you'd have something like
<select name="timezones" ng-model="$ctrl.user.business.timezone" ng-options="item as item.abbr for item in $ctrl.timezones track by item.abbr"></select>
iam newbie and i want to ask.
i want to get some value from JSON API (title, course_id, etc), and put the Value to my Template with Directive. so at Index, i can repeat my tempalate with data from the API.
How to get Value from that JSON ?
This my Code :
my API
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://192.168.1.37:8000/api/courses/a/",
"title": "I Love You", <-- I want to put this Value to my Template
"course_id": "1",
"starting_date": "2016-10-03"
}
]
}
Controller demo.js
demo.controller("demo", function($scope, $http) {
$http.get('http://192.168.1.37:8000/api/courses/'). <-- Data From my API
then(function(response) {
$scope.courses = response.data;
});
});
demo.directive("demoItemDirective", function() {
return {
scope : { demoInfo : "=info"},
templateUrl : "/app/demo.tmpl" <-- My Template
};
});
My Template demo.tmpl
<p>{{demoInfo.count}}</p> <-- Works, count Displayed
<p>{{demoInfo.results.title}</p> <-- Not works, title not displayed
My Index.html
<div ng-repeat="group in courses | groupCount:2">
<div ng-repeat="x in group">
<demo-item-directive info="x"></demo-item-directive>
</div>
</div>
It should be
<p>{{demoInfo.results[0].title}</p>
Your result contain an Array of object.
You need to access with index.
According to your post, the result is an array:
"results": [
{
"url": "http://192.168.1.37:8000/api/courses/a/",
"title": "I Love You", <-- I want to put this Value to my Template
"course_id": "1",
"starting_date": "2016-10-03"
}
]
Thus, you can't refer to the title itself, you have to reference the first element:
{{demoInfo.results[0].title}}
I have quite an interesting question (I hope) for all you AngularJS gurus out there. I am looking to create a dynamic list of form input fields based on a SELECT dropdown. As an example, we have a number of categories with each category having a set of specifications which are unique to that category. To help with the explanation we have the following:
Firstly, in the controller we start by initializing the models.
$scope.category = {};
$scope.category.specs = [];
Next we ready the data to be used in the form (actually retrieved from the server via $http). We also initialize a variable to the first element in the categories array.
$scope.categories = [
{ "id": "1", "name": "mobile", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Camera type" } ] },
{ "id": "2", "name": "laptop", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Graphics Card" } ] }
};
$scope.selectedCategory = $scope.categories[0];
In the form, we have a dropdown which when selected loads the appropriate input fields specific to that category. We use the ngRepeat directive to accomplish this. This is a dynamic list of fields based on $scope.categories.specs. (please note the ???)
<select ng-model="selectedCategory" ng-options="category.name for category in categories"></select>
<div ng-repeat="spec in selectedCategory.specs">
<label>{{spec.label}}</label>
<input type="text" ng-model="???">
</div>
Ultimately, when the user clicks the submit button, we would like to extract the category he/she has selected and then package it together with the specifications they have filled in. The post request should contain something like the following for instance (of course, I only included one spec item, but in reality there would be many):
{ "id": "1", specs [ { "id": "2", "details": "RADEON HD 8970M" } ] }
Unfortunately I am not really sure how to accomplish this. I need to somehow create an array for the spec model, and then ensure that both the ID and user entered data are appropriately extracted... what goes in the ??? and what do we do after? Any help would be much appreciated.
this is how I do it. I make a form, validate it with angular, and then when its valid I submit it with a function.
<form name="signup_form" novalidate ng-submit="signupForm()"></form>
$scope.signupForm = function() {
var data = $scope.signup;
$http({
method : 'POST',
url : 'http://yoursite.com/mail.php',
data : $.param(data), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
})
.success(function(data) {
});
}
also if you want to look at another form validation system for angular check out http://nimbly.github.io/angular-formly/#!/ It may help you solve your current form system.
In the controller, initialize $scope.specDetails as follows:
$scope.specDetails = {};
angular.forEach($scope.categories, function (category, index1) {
$scope.specDetails[category.id] = {};
angular.forEach(category.specs, function (spec, index2) {
$scope.specDetails[category.id][spec.id] = '';
});
});
In the html, replace "???" with specDetails[selectedCategory.id][spec.id]
I have a view model containing 2 arrays. One array is an array of users, and the other is an array of user levels.
{
"Users": [
{
"UserLevel": {
"Permissions": [],
"Id": 2,
"Name": "Developer",
"SortOrder": 1,
"IsHidden": false
},
"Id": 1,
"Username": "Björn Jakobsson",
"Password": null,
"Fullname": null,
"Email": "bjiorn#bjinteractive.se",
"Phone": null
}
],
"UserLevels": ko.observableArray([
{
"Permissions": [],
"Id": 1,
"Name": "Admin",
"SortOrder": 2,
"IsHidden": false
},
{
"Permissions": [],
"Id": 2,
"Name": "Developer",
"SortOrder": 1,
"IsHidden": false
}
])
}
and the drop down
<select data-bind="options: $parent.UserLevels(), optionsText:'Name', value: UserLevel" class="form-control"></select>
While editing a user from the user array i have a dropdown for choosing user level of this user wich is populated from the UserLevels array. If I choose a user level (in this case Developer) and saves the value in my database is saved and everything, and a reload of the page shows the correct value, but as soon as I choose to edit the user (using a bootstrap modal and with-data binding, the drop down automatically selects Admin (first in the array) and not Developer from my user model, and then the user model is updated since the user level of the user is bound to the drop down.
I believe your binding is incorrect. You are not binding to the observable array, but instead to what the observable array resolves to (i.e. the array)
Use
options: $parent.UserLevels
instead of
options: $parent.UserLevels()
You probably need to add an optionsValue binding.
From doc:
Typically you’d only want to use optionsValue as a way of ensuring
that KO can correctly retain selection when you update the set of
available options. For example, if you’re repeatedly getting a list of
“car” objects via Ajax calls and want to ensure that the selected car
is preserved, you might need to set optionsValue to "carId" or
whatever unique identifier each “car” object has, otherwise KO won’t
necessarily know which of the previous “car” objects corresponds to
which of the new ones.
I found a way to get around the problem with my own biding instead for value. Below is the code I use. Any drawbacks or mistace to edit? I'm pretty new to KO and still have problems sometimes when to use unwrap, unwrapobservable etc, but below code works. Ideas for improvement?
ko.bindingHandlers.valueBasedOnObject = {
init: function (element, valueAccessor, allBindings) {
var prop = allBindings().optionsValue;
var value = valueAccessor();
$(element).change(function () {
var value = $(element).val();
var selectedModel = ko.utils.arrayFirst(ko.unwrap(allBindings().options()), function (item) {
return ko.utils.unwrapObservable(item[prop]) == value;
});
valueAccessor()(selectedModel);
});
var valueUnwrapped = ko.unwrap(value);
$(element).val(valueUnwrapped[prop]);
},
update: function (element, valueAccessor, allBindings) {
/* */
}
};
I'm not sure what I'm missing here but I'm trying to update a value inside an array, and then have this reflected in the repeater. Do I need to make a copy or something before applying the update in order for Angular to show the changes?
---sample json
"lists": [
{
"name": "one",
"enabled": true
},
{
"name": "two",
"enabled": false
}
]
!-- code
setTimeout(function(){
$scope.$apply(function(){
$scope.lists[1].enabled = true;
});
},1);
!--- html
<span data-ng-repeat="list in lists | filter: {enabled: true}"></span>
From the "other controller" you are talking about broadcast an event:
$rootScope.$broadcast('listChange', listArray);
Then in the controller that controls your $scope.lists value, listen for the event:
$scope.$on('listChange', function(event, list) {
$scope.$apply(function() {
// Update goes here
});
});
It might help if you use angulars built-in timeout function $timeout.
$timeout(function(){
$scope.lists[1].enabled = true;
},1);
Documentation here: https://docs.angularjs.org/api/ng/service/$timeout
Add your lists variable to the $scope inside your controller like this:
$scope.lists = [{
"name": "one",
"enabled": true
},
{
"name": "two",
"enabled": false
}];
You also have to add something inside the <span>, because the Html you posted would not display anything. (You need to do something inside the <span> tag in order to show something)
<span ng-repeat="list in lists | filter:{enabled: true}">{{list.name}}</span>
Now when you update the lists variable, this will be reflected in the Html immediately.
Works fine for me. Hope i could help!