$scope.$digest() doesn't populate select2 drop down list - angularjs

I have 2 drop down lists using ui-select2
<label class="control-label" for="MakeSelect">Make </label>
<select class="form-control col-md-2" id="MakeSelect" name="make" ui-select2
ng-model="carDetails.make">
<option ng-if="!carDetails.make" value="">[SELECT]</option>
<option ng-repeat="make in makes" value="{{ make }}">{{ make}}</option>
</select>
</div>
<div class="col-md-5">
<label class="control-label" for="ModelSelect">Model </label>
<select class="form-control col-md-2" id="ModelSelect" name="make" ui-select2
ng-model="carDetails.model">
<option ng-repeat="model in models" value="{{ model }}">{{ make}}</option>
</select>
After I choose a value in the drop down list "Makes" I am activating a watch that inside it I load the content of "Models" Dropdown lists.
Then, In order to refresh the drop down lists content in the GUI I call $scope.$digest() :
$scope.$watch('carDetails.make', function (make) {
console.log('selected make is: ' + make);
if (make == "") {
return;
}
Parse.Cloud.run('getCarModels', {'Make': make}, {
success: function (results) {
$scope.parseModels = results.resultSet;
$scope.models = results.distinctModels;
$scope.$digest();
},
error: function () {
console.log("Error: Failed to load models");
console.log(Parse.Error);
}
});
The problem is that with $digest the selected value of the first drop down list is becoming null and without it just doesn't refresh the view.
Any suggestions please?

They're both pointing to the same scope model, carDetails.make. So, of course, the first will become null, because the second drop down list sets carDetails.make to null. Also, I don't think you need to use digest, although, you should be using $scope.$apply. But, angularjs should run the digest anyway.

Related

Show/Hide Text based on onchange of select

Using AngularJS, there is a requirement to show a dropdown with a selected value:
- When user selects a different value we should show a warning message and shouldn't proceed with update (save button disable).
- When user reverts to the original value, the message should hide and able to update (save button enable)
<select ng-model="vm.sldetails.AgencyGroupID" onchange=""
ng-options="a.AgencyGroupID as a.AgencyGroupName for a in vm.agencygroups">
<option value="">--Select--</option>
</select>
<label ng-show="">Warning message</label>
Instead of calling an event in controller, can we achieve directly in Onchange event?
<div class="col-md-2">
<select class="form-control" ng-model="vm.sldetails.AgencyGroupID"
ng-options="a.AgencyGroupID as a.AgencyGroupName for a in vm.agencygroups">
<option value="">--Select--</option>
</select>
</div>
HTML:
<label class="col-md-2 control-label text-align-left" id="lblWarningMessage" ng-if="vm.sldetails.AgencyGroupID==='your value'">Warning message</label>
In label tag,your value should be replaced by ur compare value
I guess you could try something like this:
<select ng-model="vm.sldetails.AgencyGroupID" ng-change="vm.selectChanged()"
ng-options="a.AgencyGroupID as a.AgencyGroupName for a in vm.agencygroups">
<option value="">--Select--</option>
</select>
<label ng-show="vm.showWarning">Warning message</label>
And in js:
vm.selectChanged = function(){
if(vm.sldetails.AgencyGroupID !== 'the initial value'){
vm.showWarning = true;
}else{
vm.showWarning = false;
}
}

How to remove item from an array

I have a dropdown where items are populated from $scope.role. Now I need to remove the values from $scope.role once the value is added or selected in dropdown. I did splice(index,1) which actually delete the first element only. Need assistance.
$scope.role = ['Actor', 'Director/ Asst. director', 'Lyricist',
'Music director/ Asst. director', 'Singer', 'Standup Comedian', 'Model',
'Cinematographer', 'Photographer', 'Script Writer', 'Choreographer',
'Editor/ Promo editor', 'Costume designer', 'Art director', 'Stunt artist',
'Voice-over artist', 'Graphic Designer', 'Screenplay', 'Dialogue',
'Back ground music'];
Html:
<div class="row newRow">
<div class="form-group fields col-sm-2 col-xs-4">
<label>ROLE *</label>
<select name="role" class="form-control1 drop2" required ng-model="model.role" placeholder="select">
<option value='' disabled selected>Select</option>
<option ng-repeat="item in role track by $index" value="{{item}}">{{item}}</option>
</select>
</div>
<div class="form-group col-sm-2 col-xs-4">
<button ng-click="AddRole()">Click to Add Role</button>
</div>
</div>
JS:
$scope.multiRoles = [];
$scope.role == $scope.dummy;
$scope.rolesAdded = false;
$scope.AddRole = function(index) {
debugger;
if ($scope.model.role !== undefined) {
$scope.multiRoles.push($scope.model.role);
$scope.role.splice(index, 1);
console.log($scope.role);
}
};
You can do it in two ways 1) As suggested by #nikjohn by sending your $index of dropdown in ng-click = "AddRole($index)" and then splice or else
2) You can find the index of the selected option by using the ng-model binded to the dropdown.
$scope.AddRole = function(){
debugger;
if($scope.model.role !== undefined ){
$scope.multiRoles.push($scope.model.role);
var index = $scope.role.indexOf($scope.model.role); //just find the right index which is the selected option in dropdown.
$scope.role.splice(index,1);
console.log($scope.role);
}
};
In your HTML, pass $index to the AddRole. Otherwise, the function does not know what $index is, and also include the button within the ng-repeat:
<select name="role"
class="form-control1 drop2" required
ng-model="model.role" placeholder="select">
<option value='' disabled selected>Select</option>
<option ng-repeat="item in role track by $index" value="{{item}}"> {{item}}
<button ng-click = "AddRole($index)">Click to Add Role</button>
</option>
</select>
In your Controller, there's an extra = that I've highlighted in my comment:
$scope.multiRoles = [];
$scope.role == $scope.dummy; // Why a `==` here? This should be a `=`
$scope.rolesAdded = false;
$scope.AddRole = function(index){
debugger;
if($scope.model.role.length){ // Cleaner method to verify that the array is non-empty
$scope.multiRoles.push($scope.model.role);
$scope.role.splice(index,1);
console.log($scope.role);
}
};
May I also suggest that you use Angular's select implementation with ng-options because:
Choosing between ngRepeat and ngOptions
In many cases, ngRepeat can be used on elements instead of ngOptions to achieve a similar result. However, ngOptions provides some benefits:
more flexibility in how the <select>'s model is assigned via the select as part of the comprehension expression
reduced memory consumption by not creating a new scope for each repeated instance
increased render speed by creating the options in a documentFragment instead of individually
Specifically, select with repeated options slows down significantly starting at 2000 options in Chrome and Internet Explorer / Edge.

Angular Empty option (Dynamic input)

Been searching all over Stackoverflow and there is loads of tips on how to remove the 'dreaded' empty (undefined) options element in a select dropdown. However I have yet to find an answer for when my code looks like this:
--VIEW--
<form class="simple-mods">
<fieldset ng-repeat="modifier in modifiers">
<label for="{{ modifier.id }}">{{ modifier.title }}</label>
<select name="" id="{{ modifier.id }}" ng-model="mods[modifier.id]" name="modifier[{{ modifier.id }}]" ng-mod="{{ modifier.title }}">
<option value="{{ variation.id }}" ng-repeat="variation in modifier.variations">{{ variation.title }}</option>
</select>
</fieldset>
<fieldset>
<button ng-click="addCart()" ng-if="!addStatus" class="btn btn-success" translate>Add to cart</button>
<button ng-if="addStatus" class="btn btn-warning" ng-bind-html="addStatus">{{ addStatus }}</button>
</fieldset>
</form>
-- CONTROLLER --
.controller('ProductCtrl', function ($scope, $rootScope, moltin, $timeout, product) {
var productId = product.id,
qty = 1,
mods = {};
$scope.product = product;
$scope.addStatus = null;
$scope.modifiers = product.modifiers;
});
If any one can help I would be very grateful.
#BETTY it doesnt seem to work. I have attached 2 screenshots
Screen shot 3
Screen shot 4 (Value is now a string)
#betty
<fieldset ng-repeat="modifier in modifiers" ng-init="mod[modifier.id] = modifier.variations[0].id">
<label for="{{ modifier.id }}">{{ modifier.title }}</label>
<select id="{{ modifier.id }}" ng-model="mods[modifier.id]" ng-options="variation.id as variation.title for variation in modifier.variations">
<option></option>
</select>
</fieldset>
Try to clean up modifier.variations in your controller, deleting undefined elements from modifier.variations
$scope.modifier.variations = $scope.modifier.variations.filter(function(n){ return n != undefined });
You need to inject $scope in your controller.
You need to set the ng-model right (=> mods[modifier.id]), either by using ng-init or setting it in the controller..
This solution uses ng-init which sets the default value to the first variation ID. I also removed everything you don't need and used ng-options (reduces some HTML ;)).
<fieldset ng-repeat="modifier in modifiers" ng-init="mods[modifier.id]=modifier.variations[0].id">
<label for="{{ modifier.id }}">{{ modifier.title }}</label>
<select id="{{ modifier.id }}" ng-model="mods[modifier.id]" ng-options="variation.id as variation.title for variation in modifier.variations">
<option></option>
</select>
</fieldset>
I also recommend adding an empty option-tag, here is why: ng-model is getting wrong value from dropdown
AND you need $scope.mods = {}; in the controller instead of var mods = {}; because you are using mods in the HTML!
Maybe you also need to use track by variation.id so that the selected value can be checked right (ng-model and option value). I answered a similar question and track by was the answer, see https://stackoverflow.com/a/32999399/595152 ;)

ionic/Angularjs - not able to unchecked check box on ng-change

I have one drop down and a check box, i want to reset check box value to false whenever drop-down value change. I had already written code for reset check box value to false, but it is not working, please tell me where i am doing wrong.
View:
<label class="item item-input item-select">
<div class="input-label">Leave Type</div>
<select ng-model="LeaveRequest.leaveType" ng-change="leavetypechange(LeaveTypes)" required>
<option value="">Select Leave Type</option>
<option ng-repeat="lt in LeaveTypes"value="{{lt.Name}} ">{{lt.Name}}</option>
</select>
</label>
<div ng-show="ShowPeriod">
<ion-checkbox ng-model="isChecked" >Half day/ Quarter leave</ion-checkbox>
</div>
controller:
.controller('ApplyLeaveCtrl',function($scope, $state, $templateCache,$ionicPopup) {
$scope.leavetypechange=function(){
$scope.isChecked=false;
};
});
$scope.isChecked in loop is creating seperate scope for each item in dropdown.
so you need to put it in service.
.service('dataService', function() {
this.isChecked;
})
here is you working codepen:
http://codepen.io/anon/pen/MwzLqO
Use $parent with isChecked as follow:
<ion-checkbox ng-model="$parent.isChecked" >Half day/ Quarter leave</ion-checkbox>

AngularJS compile rendered name value in dynamic form

I'm building a form dynamically in Angular.
All works great until I get to my validation directive.
This uses the form object to get the field name and apply styling to it to show errors in invalid fields.
However because it's dynamically set the name appears as {{field.name}} not the actual name rendered in the browser.
Here is my markup
<div class="form-group" ng-repeat="field in fields">
<label class="text control-label col-sm-2" for="{{field.name}}">{{field.label}}</label>
<div class="input-group col-sm-9" ng-switch="field.type">
<input ng-switch-when="email" type="email" name="{{field.name}}" class="form-control" id="{{field.name}}" placeholder="{{field.label}}" ng-model="field.value" required>
<input ng-switch-when="text" type="text" name="{{field.name}}" class="form-control" id="{{field.name}}" placeholder="{{field.label}}" ng-model="field.value" required>
<select ng-switch-when="select" id="{{field.name}}" name="{{field.name}}" id="{{field.name}}" ui-select2="" ng-model="field.value" placeholder="{{field.label}}" required>
<option></option>
<option ng-repeat="option in field.options" value="{{option.value}}">{{option.label}}</option>
</select>
<p ng-switch-default>Need template for {{field.type}}</p>
</div>
</div>
Here's where I check for errors in my directive
// go through every field
for(var errorType in form.$error)
{
var fields = form.$error[errorType];
// loop through all fields of this type
for(var j = 0 ; j < fields.length ; j++)
{
var field = fields[j];
console.log(field);
var $field = element.find('[name='+field.$name+']');
showErrors($field, field, errorType);
}
}
And here are the properties for one of the invalid fields when logged out
...
$invalid: true
$isEmpty: function (value) {
$modelValue: ""
$name: "{{field.name}}"
$parsers: Array[1]
$pristine: true
...
So when I try to get hold of the field using var $field = element.find('[name='+field.$name+']'); it obviously doesn't work and I get a error...
unrecognized expression: [name={{field.name}}]
How would I get around this and get the rendered name. I need this directive to work for forms that aren't dynamically created either (in which case it works fine).
You have to use a directive:
myApp.directive("dynamicName",function($compile){
return {
restrict:"A",
terminal:true,
priority:1000,
link:function(scope,element,attrs){
element.attr('name', scope.$eval(attrs.dynamicName));
element.removeAttr("dynamic-name");
$compile(element)(scope);
}
};
});
Here is a fiddle.
Full answer here.

Resources