Set default value on selected ng-model and manage ng-change - angularjs

I cannot set the default value for my selected Item knowing that I'm supposed to get the default value from a json () use that selected value to show another form.
In my controller I have set the selected this way:
.controller('attributeFacetCtrl', function ($scope, tabsService, $location, contentService, attribute) {
$scope.attribute = attribute;
$scope.types = [{
val: 'terms'
}, {
val: 'continuous'
}];
$scope.selected = $scope.attribute.facet.data.type;
$scope.isTerms = false;
$scope.validateFrom = function() {
var chk = $scope.selected.val;
if (chk === 'terms') {
$scope.isTerms = true;
} else {
$scope.isTerms = false;
}
};
})
the result of $scope.attribute.facet.data.type="terms"
And in my view I have this
<div class="form-group">
<label class="wk-field-label">
<i class="icon-asterisk wk-prefield wk-mandatory"></i>
Type
</span>
</label>
<select class="wk-field-input" ng-model="selected"
ng-options="typeValue as typeValue.val for typeValue in types"
ng-change="validateFrom()"
required></select>
</div>
<div ng-if="isTerms" ng-repeat="orders in attribute.facet.data.order">
<div>
<label class="wk-field-label">
<i class="icon-asterisk wk-prefield wk-mandatory"></i>
Order
</span>
</label>
</div>
</div>

The problem is that you're setting $scope.selected to a string ("terms"), but when you're loading up ng-options it's loading it with objects that have a val property.
If you don't necessarily need $scope.selected to be an object, then you can change your ng-options to the following:
ng-options = "typeValue.val as typeValue.val for typeValue in types"
If you require $scope.selected to be an object with a val property then you will need to set its initial value appropriately and not set it to a string in order to set the default selection.

Since you want to set the element by string, change your select element to the following:
<select
class="wk-field-input"
ng-model="selected"
ng-options="typeValue as typeValue.val for typeValue in types"
ng-change="validateFrom()"
required
>
</select>
You can read more about how to use as here: https://docs.angularjs.org/api/ng/directive/ngOptions
Hope that helps!

Related

Angularjs Select values are getting removed from ngModel after being added programmicatically

I am using Angularjs with select2. I have a multiselect box that gets populated based off the values selected in another dropdown. I use an click event on a button for fire a method that adds a list of ids to the ngModel object assigned to the multiselect box. I can see the values getting added properly after I trigger a change event on that form element because even after reading articles and changing the ngModel value to be a object and not an array, the values still aren't binding when I add them programmatically. After I trigger the change event on the form element, I am able to see some of the values but not all of them. Some of the values were removed. Below is my code.
addRecord.vm
<div class="col-sm-4">
<select ui-select2="{ allowClear: false, minimumResultsForSearch: 10, theme: bootstrap }"
name="recordTemplate" ng-model="addRecordCtrl.selectedTemplate">
<option class="selectPlaceholder" value="" disabled selected hidden>- Chose Record Template -</option>
<option ng-repeat="template in addRecordCtrl.recordTemplates" value="{{record.name}}">{{record.name}}</option>
</select>
</div>
<div class="col-sm-9">
<button id="addButton" class="btn btn-primary btn-lg" ng-click="addRecordCtrl.addRecords()" ng-disabled="addRecordCtrl.isLoading
|| addRecordCtrl.isEdit">Add</button>
</div>
<div class="col-lg-9 col-xs-9" id="recordContainer" name="recordContainer">
<select ui-select2="{ allowClear: false, minimumResultsForSearch: Infinity}"
name="records" id="records" class="medium"
multiple ng-model="addRecordCtrl.records.id"
ng-required="true" ng-cloak>
<option ng-repeat="record in addRecordCtrl.availableRecords | notInArray:addRecordCtrl.selectedRecordIds.ids:'recordId'"
value="{{record.recordId}}">{{record.name}}</option>
</select>
<input type="hidden" ng-model="addRecordCtrl.selectedRecordName" value="">
</div>
app.js
recordApp.controller('RecordController', ['$http', '$window', '$modal', '$log','$filter', '$timeout', function ($http, $window, $modal, $log, $filter, $timeout) {
var self = this;
self.availableRecords = [{
recordId: "1",
name: "Love and Happiness"
},{
recordId: "2",
name: "Feel the Burn"
},{
recordId: "3",
name: "Juicy Baby"
}];
self.recordTemplates = null;
self.selectedRecordIds = {};
self.addRecords = function () {
//add record ids from the selected records.
self.recordTemplates.recordId.forEach(function (id) {
self.selectedRecordIds.ids.push(id.recordId);
});
self.recordAdded = true;
};
}]);
//filter to filter out ids that have already been selected.
recordsApp.filter('notInArray', ['$filter', function($filter){
return function(list, arrayFilter, element){
if(arrayFilter){
return $filter("filter")(list, function(listItem){
for (var i = 0; i < arrayFilter.length; i++) {
if (arrayFilter[i][element] == listItem[element])
return false;
}
return true;
});
}
};
}]);
The reason some of my values were getting deleted from the selectedRecordIds array after adding them programmatically was because they are not in the availableRecords array. Once I made sure those values where in the availableRecords array all was well.

Checkbox Input is returning Boolean values when placed in view model AngularJS

I have the following HTML markup:
<div class="blog-admin-article-sidebar-item-content">
<div class="checkbox">
<label><input ng-model="vm.newArticle.category" type="checkbox" value="Volkswagen">Volkswagen</label>
</div>
<div class="checkbox">
<label><input ng-model="vm.newArticle.category" type="checkbox" value="SEAT">SEAT</label>
</div>
<div class="checkbox">
<label><input ng-model="vm.newArticle.category" type="checkbox" value="SKODA">SKODA</label>
</div>
<div class="checkbox">
<label><input ng-model="vm.newArticle.category" type="checkbox" value="Pulman Group">Pulman Group</label>
</div>
</div>
As you can see my input check-box's have custom values such as Volkswagen for example.
For some reason I seem to be having an issue with selecting the check-box's and placing the value within my view model.
Here is an example of my controller:
(function(){
'use strict';
angular
.module('app.admin')
.controller('AdminController', AdminController);
AdminController.$inject = ['$firebaseArray'];
function AdminController($firebaseArray) {
var vm = this;
var fireArticles = new Firebase('XXX');
function Article() {
this.name = '';
this.content = '';
this.category = '';
this.published = false;
}
vm.newArticle = new Article();
vm.articles = $firebaseArray(fireArticles);
vm.addArticle = addArticle;
function addArticle() {
vm.articles.$add(vm.newArticle);
}
}
})();
As you see I am declaring my View Model named as vm.
I'm quite confused why the checkbox value is being placed within my vm.newArticle.category as a Boolean value and not the value that is assigned to the checkbox?
My view model is currently outputting:
"category":true
Any help with this would be great, thanks.
Based on your use case, a checkbox seems to be the wrong control because article.category can only ever have one value and a checkbox would allow multiple selections. In this case, I would recommend using radio buttons example
However, if you did want to support multiple categories being selected at the same time I would recommend this approach.
function Article() {
this.name = '';
this.content = '';
this.category = {
skoda: false,
seat: false,
Volkswagen: false
}
}
An html:
<input ng-model="vm.newArticle.category.skoda"type="checkbox">SKODA</label>
If you have to bind some value upon checking and unchecking the checkbox use
ng-true-value="someValue" and ng-false-value="someValue".
You can use "select" control instead of checkbox.
for example:
<select ng-model="vm.newArticle.category" required>
<option value="Volkswagen">Volkswagen</option>
<option value="SEAT">SEAT</option>
<option value="SKODA">SKODA</option>
</select>
and you will have your "category" populated as string in your object.
if you are using boolean variable to bind the checkbox please refer the below example:
<div ng-repeat="book in books">
<input type="checkbox" ng-model="book.selected" ng-
click="function(sample)">
</div>

How Can I set the ng-disabled value of a button based on the original value of a model

I am attempting to disable a button which is next to a checkbox, but only if the underlying model of the checkbox is different from the original value. Pristine on it's own doesn't work because technically the form has been changed. My solution was to grab the original value and toggle the pristine value of the form based on whether current value is equal to that value.
I'm assuming there is a better way which I am unaware of.
<div ng-controller="MyCtrl">
<div ng-form="form">
<div class="checkbox">
<label>
<input type="checkbox" ng-click="toggle(form)" ng-model="foo.bar">{{ foo.bar }}
</label>
</div>
<button class="btn btn-primary" ng-disabled="form.$pristine" ng-click="save(form)">Button</button>
</div>
</div>
angular.module("app", [])
.controller("MyCtrl", function($scope, $timeout){
//catch when scope is first set
$scope.$watch("foo", function(curr, prev){
if(curr && !prev)
$scope.original = curr.bar;
});
//assume this is being set by some other scope
$timeout(function(){
$scope.foo = {
bar: true
};
}, 500);
$scope.toggle = function(form){
if($scope.original == $scope.foo.bar)
form.$setPristine();
console.log(form.$pristine);
};
$scope.save = function(form){
$scope.original = $scope.foo.bar;
form.$setPristine();
};
});
I don't understand why you use $pristine, or a $watch.
Just store the original value in a scope variable when the controller is instantiated, and use
ng-disabled="foo.bar != original"

Resetting form controls after action in Angular

Need a bit of help with this. I am trying to get Angular to reset value of my input box after add control is invoked. This is kind of important when it comes to drop down select boxes. I want to be able to clear what user has selected after the option is pushed to a collection.
I also seems to have an issue with user.fName updating whatever I previously added to the users array but it's probably related to the above.
Also can you see what I am doing wrong with ng-show?
html
<div ng-controller="UserController" name="form">
<div ng-show="form.fName.$touched">Hello {{ user.fName }}</div>
<input type="text" name="fName" ng-model="user.fName">
<a ng-click="addUser(user)">Add</a>
<br>
<div ng-repeat="user in users">{{ user }}</div>
</div>
javascript
function UserController($scope) {
//$scope.user = {
// fName: "Joe",
// lName: "Doe"
//};
$scope.users = [];
$scope.addUser = function (user) {
if($scope.users.indexOf(user) === -1){
$scope.users.push(user);
} else {
// trigger error/notification message
console.log(user, ' already added');
}
user = {}; //clear user
};
}
ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope.
You are currently not using the scoped property in your click action but a copy that is passed as a parameter. Change user to $scope.user in your addUser method
Note: your object comparison to identify already added users won't work as you always create new objects that will never match. Change it to some different comparison method like comparing the fName properties.
html
<div ng-controller="UserController" name="form">
<div ng-show="form.fName.$touched">Hello {{ user.fName }}</div>
<input type="text" name="fName" ng-model="user.fName">
<a ng-click="addUser()">Add</a>
<br>
<div ng-repeat="user in users">{{ user }}</div>
</div>
javascript
function UserController($scope) {
$scope.users = [];
$scope.addUser = function () {
if($scope.users.indexOf($scope.user) === -1){
$scope.users.push($scope.user);
} else {
// will never match as indexOf() will always return -1
console.log($scope.user, ' already added');
}
$scope.user = {}; //clear user
};
}
http://plnkr.co/edit/N5FXJdWRl42YrVwJsUuR?p=preview
As for your ng-show question: $touched was introduced in AngularJS 1.3 and you're referencing AngularJS 1.2.x in your Plunker code.

Dynamically add input fields with Angular and perform validation on blur

Form at start has 1 input field for address. Bellow there is a link that when clicked adds another input and so on. There is no limitation in number of fields.
Is there more elegant way of adding new elements in model collection in Angular? I'm currently using an array of null elements, and on the link click I just push another null in that array so ng-repeat picks it up. And when I want to submit form I go through that array and filter out elements that are not null.
When input field is focused out/blurred there should be validation performed. I'm currently calling a function from controller on ng-blur event but I'm having trouble passing it current input text value.
Fiddle
HTML:
<div ng-app="TestApp">
<div ng-controller="MainCtrl">
<div ng-repeat="field in fields track by $index">
<input type="text" placeholder="enter the address" ng-model="fields[$index]" ng-blur="validate()" />
</div>
+ Add another input
<br/>
<br/>
List addresses
</div>
</div>
JS:
var app = angular.module("TestApp", []);
app.controller("MainCtrl", function($scope){
$scope.fields = [null];
$scope.addresses = [];
$scope.addField = function(){
$scope.fields.push(null);
};
$scope.listAddresses = function(){
for(var i in $scope.fields){
if($scope.fields[i] !== null){
$scope.addresses[i] = $scope.fields[i];
}
}
alert("Addresses: " + $scope.addresses);
};
$scope.validate = function(){
console.log("Should validate current input");
};
});
Instead of using two arrays, use one and store objects:
$scope.items =
[
{ address: '' }
];
It will now be clearer what the model of the input is, as you don't have to use $index. You can also pass the item to the validate function:
<div ng-repeat="item in items">
<input type="text" ng-model="item.address" ng-blur="validate(item)" placeholder="enter the address" />
</div>
Adding item:
$scope.addItem = function() {
$scope.items.push({ address: '' });
};
Demo: http://plnkr.co/edit/sPlPO2DfrgNHf5AasYlH?p=preview

Resources