watching on the select item in Angularjs - angularjs

I am having a div which contains a set of dropdown to select a criteria. We can add or delete criteria using the plus and minus buttons. The values to fill in the dropdown is fetched from an API.
The code for the UI is below:
<form novalidate="" role="form" name="filterForm" class="form-inline">
<div ng-repeat="criteria in criterias">
<div class="m-b">
<div class="form-group s-b" style="width: 150px;">
<span>Country</span>
<select class="form-control" ng-options="item for item in country" name="account" ng-model="criteria.country" style="max-width:100%"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>State</span>
<select ng-options="item for item in state" class="form-control" name="account" ng-model="criteria.state" style="max-width:100%"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>City</span>
<select class="form-control" ng-options="item for item in city" name="account" ng-model="criteria.city" style="max-width:100%;"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>Predicate</span>
<select class="form-control" name="account" ng-model="criteria.predicate" style="max-width:100%">
<option value="matches">Matches</option>
<option value="not-matches">Not Matches</option>
</select>
</div>
<div class="form-group s-b" style="width: 100px;">
<span>Value</span>
<select class="form-control" ng-options="item for item in value" name="account" ng-model="criteria.value" style="max-width:100%;"></select>
</div>
<div class="form-group s-b" style="margin-top: 20px;">
<span>
<button class="btn btn-sm btn-primary pad-btn" type="submit" ng-click="addCriteria()">
<i class="fa fa-plus"></i>
</button>
<button class="btn btn-sm btn-danger pad-btn" type="submit" ng-click="deleteCriteria(criteria)">
<i class="fa fa-minus"></i>
</button>
</span>
</div>
</div>
</div>
<button class="btn btn-sm btn-primary pad-btn align-center" type="submit" ng-click="searchParams(filterForm)">Submit
<i class="fa fa-check"></i>
</button>
<button class="btn btn-sm btn-warning pad-btn align-center" type="submit" ng-click="resetFilter()">Reset
<i class="fa fa-reply"></i>
</button>
</form>
I need to watch for the dropdown and handle the event for the corresponding criteria and update the other corresponding dropdown elements for that criteria. Please let me know how to handle the $watch element when there are many criterias when user has added using the plus button as I am not advanced programmer on AngularJs.
Updated Question
Based on the suggestion I have used the ng-change instead of $watch and I am now able to handle the event and also get the reference to the criteria object. After handling the event, I need to update the state value for the selected country. I have updated the Plnkr link with the code below but the state drop down is not getting updated even after updated the scope using $scope.criterias[index] = user;. Please let me know if I am missing something.
Updated code to handle the change event:
$scope.handleClassification = function(index){
var user = $scope.criterias[index];
user.config=["California"];
$scope.criterias[index] = user;
console.log(user);
}
I am providing the updated plnkr link for more details - Plnkr

Try this way..I guess you want to update select in a cascade way...
Your HTML file:
<div ng-controller="StaticCtrl">
<h1>Static - Oriented</h1>
<p>This approach may be better when you have the entire dataset</p>
<div>
Country:
<select id="country" ng-model="cities" ng-options="country for (country, cities) in countries" ng-change="onChange()">
<option value=''>Select</option>
</select>
</div>
<div>
State: <select id="city" ng-disabled="!cities" ng-model="suburbs" ng-options="city for (city, suburbs) in cities"><option value=''>Select</option></select>
</div>
<div>
City: <select id="suburb" ng-disabled="!suburbs" ng-model="suburb" ng-options="suburb for suburb in suburbs"><option value=''>Select</option></select>
</div>
</div>
and your JS:
function StaticCtrl($scope) {
$scope.countries = {
'India': {
'UP': ['Noida', 'Lucknow', 'Agra'],
'Maharashtra': ['Mumbai']
},
'USA': {
'San Francisco': ['SOMA', 'Richmond', 'Sunset'],
'Los Angeles': ['Burbank', 'Hollywood']
},
'canada': {
'People dont live here': ['igloo', 'cave']
}
};
$scope.onChange = function() {
console.log("Asdasd");
$scope.suburb = '';
}
}
Here is the fiddle..

Related

Error/Empty in triggering form.$invalid

<form class="form-inline" name="form" novalidate>
<div class="sub-form" ng-form is-active ng-init="active = true" name="info">
<div class="col-md-4 col-sm-6 col-ie-4">
<div class="select-input">
<label for="xyz">Xyz *</label>
<i class="fa fa-check-circle success" ng-show="form.info.xyz.$valid"></i>
<i class="fa fa-spinner fa-spin"></i>
<i class="fa fa-times-circle error" ng-show="(form.info.xyz.$invalid && !form.info.xyz.$pristine)"></i>
<div class="styled-select">
<select
heights
name="xyz"
id="xyz"
ng-options="xyz.in as xyz.ft for xyz in xyzs"
ng-model="player.xyz"
required>
<option value="" selected="selected">-- Select --</option>
</select>
</div>
</div>
</div>
</div>
</form>
<div class="back-next-button-row">
<div class="red-button tiny-button next-button" ng-if="form.$valid">
<button ng-click="next()"><span class="button-text">Next</span><i class="fa fa-chevron-right"></i></button>
</div>
<div class="red-button tiny-button next-button" ng-if="form.$invalid">
<button ng-click="error()"><span class="button-text">Error</span><i class="fa fa-chevron-right"></i></button>
</div>
</div><!--back-next-button-row-->
In Script
$scope.form = {};
$scope.form.info = {};
$scope.formError = function () {
console.log($scope.form.info.xyz);
//Getting Object {}
}
While in html its showing proper objects that i expect
Basically I would like to check
if($scope.form.info.xyz.$invalid){
alert("Invlid")
}
I would be thankful if I came to know why this is creating problem in this prospect
With angular, you can do this inside the HTML and dont have to carry it to the script. If you want to check any form element is invalid or incomplete, you can add an element like this.
<p class="text-danger" ng-show="form.$invalid">Invalid</p>
If you still want to do on click, try the below.
In the HTML capture the form name on your function.
<button ng-click="next('form')">Validate</button>
In JS, you can have a function like the below,
$scope.next = function(form){
if ($scope[form].$valid) {
alert("True");
} else {
alert("Invalid");
}
};

Unable to pass dynamic form inputs to the controller function

I want a form to be created dynamically with three inputs each time a new data item is found. Whenever the end user clicks on a particular checkbox the selected field name, other input values corresponding to the form group have to be submitted to the controller function. I created a JSFiddle for the layout.
<div class="panel panel-primary" ng-controller="citycontroller as ctrl">
<div class="panel-heading">
Available Cities
</div>
<div class="panel-body">
<h4>
{{data}}
</h4>
<div ng-repeat="x in data" class="[ form-group form-inline ]">
<input class="form-control input-md" type="checkbox" id="{{x.name}}" ng-model="name" autocomplete="off" />
<div class="[ btn-group ]">
<label for="{{x.name}}" class="[ btn btn-success ]">
<span class="[ glyphicon glyphicon-ok ]"></span>
<span> </span>
</label> <label for="{{x.name}}" class="[ btn btn-default active ]">
{{x.name}}
</label>
</div>
<input class="form-control input-md" type="text" placeholder="periodicity" id="x.periodicity" autocomplete="off" />
</div>
<button type="button" class="btn btn-info" style="float: right" ng-click="ctrl.addInfo()">Add</button>
</div>
</div>
Controller method is as follows:
var mainApp = angular.module('cityinfo',[]);
mainApp.controller('citycontroller', function($scope,$http,$window,$interval) {
var cities=[{"name":"hyd","periodicity":"5"},{"name":"chn","periodicity":"5"},{"name":"blr","periodicity":"5"}];
$scope.data = cities;
this.addInfo=function() {
console.log('update city information...');
//get list of city names that are selected by the user in the form here and print their values
}
});
Not getting idea about how to retrieve form values in the controller method addInfo(). Can anyone help me in this regard.
You'll need to track which checkboxes are checked using ng-model.
One approach could be as follows.
HTML:
<div ng-repeat="city in cities">
<input type="checkbox" ng-model="city.checked" />
</div>
JS:
$scope.cities = [{
name: 'foo',
periodicity: 5,
checked: false
}, {
name: 'bar'
periodicity: 6,
checked: false
}]
$scope.addInfo = function() {
// Using lodash
_($scope.cities).filter({checked: true}).each(function(city) {
// do stuff
}
}
You don't have to change your code at all. Just by changing the ng-model of your input you can achieve it:
HTML
</div>
<div class="panel-body">
<h4>
{{data}}
</h4>
<div ng-repeat="x in data" class="[ form-group form-inline ]">
<input class="form-control input-md" type="checkbox" id="{{x.name}}" ng-model="x.value" autocomplete="off" />
<div class="[ btn-group ]">
<label for="{{x.name}}" class="[ btn btn-success ]">
<span class="[ glyphicon glyphicon-ok ]"></span>
<span> </span>
</label>
<label for="{{x.name}}" class="[ btn btn-default active ]">
{{x.name}}
</label>
</div>
<input class="form-control input-md" type="text" placeholder="periodicity" id="x.periodicity" autocomplete="off" />
</div>
<button type="button" class="btn btn-info" style="float: right" ng-click="ctrl.addInfo()">Add</button>
</div>
</div>
SCRIPT
var mainApp = angular.module('myApp',[]);
mainApp.controller('citycontroller', function($scope) {
var cities=[{"name":"hyd","periodicity":"5"},{"name":"chn","periodicity":"5"},{"name":"blr","periodicity":"5"}];
$scope.data = cities;
this.addInfo=function() {
console.log($scope.data);
//get list of city names that are selected by the user in the form here and print their values
}
});
In your browser console check for value. It will be true if checkbox is selected.

check multiple ng-model values to change the caption of the button

i need to change the caption of the button based on the value of multiple model values. i have a button. when the model values are null, it should display "Load" and if not then "refresh". If i check with one model value it works fine. How do i check entire model values.
<button id="load" type="submit" class="btn btn-success" style="float:right" > {{processState.widgetInstance.configuration.application ? 'Refresh':'Load'}}</button>
<ul>
<li>Application:
<select name="application" required ng-model="processState.widgetInstance.configuration.application" ng-options="app.APP_ID as app.APP_NAME for app in applications">
</select>
</li>
<li>Namespace:
<select name="namespace" required ng-model="processState.widgetInstance.configuration.namespace" ng-options="namespace.NAMESPACE_ID as namespace.NAMESPACE for namespace in namespace">
</select>
</li>
</ul>
In this case, if the select combo has values, it should display refresh else load. the values for the scope variables are populated from a service in this case.
Plunker
Working Copy
Just use parenthesis and && operator
angular.module("app",[]).controller("ctrl", function($scope){
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button id="load" type="submit" class="btn btn-success" style="float:right" > {{(application && namespace) ? 'Refresh':'Load'}}</button>
<ul>
<li>Application:
<input ng-model="application" type="text"/>
</li>
<li>Namespace:
<input ng-model="namespace" type="text"/>
</li>
</ul>
</div>
you can use angular form validation http://plnkr.co/edit/UZIqF2qG4UyNdbH4NSHu?p=preview
<button id="load" type="submit" class="btn btn-success" style="float:right"> {{ myform.$valid ? 'Refresh': 'Load' }}</button>
<form name='myform'>
<ul>
<li>Application:
<select name="application" required ng-model="processState.widgetInstance.configuration.application" ng-options="app.APP_ID as app.APP_NAME for app in applications">
</select>
</li>
<li>Namespace:
<select name="namespace" required ng-model="processState.widgetInstance.configuration.namespace" ng-options="namespace.NAMESPACE_ID as namespace.NAMESPACE for namespace in namespace">
</select>
</li>
<li>Products:
<select name="product" required ng-model="processState.widgetInstance.configuration.product" ng-options="product.PRODUCT_ID as product.PRODUCT_NAME for product in product">
</select>
</li>
</ul>
</form>

Splice item out of ng-repeat array, when that item is clicked

I have an array of items that I'm repeating.
<li ng-repeat="lineItem in lineItems" class="bouncy-slide-left">
<div class="form-group col-sm-5 col-lg-2 col-xl-2 pad-right">
<label for="expenses">{{lineItem.labels.name}}Expense:</label>
<br>
<select name="expenses" ng-model="expense.name" class="form-control" style="width: 175px;">
<option value="{{expense.name}}" ng-repeat="expense in expenses">{{expense.name}}</option>
</select>
</div>
<div class="form-group col-sm-5 col-lg-2 col-xl-2 pad-right">
<label>Material Cost:</label>
<br>
<input type="text" ng-model="expense.cost" class="form-control" name="material" placeholder="5.00">
</div>
<div class="form-group col-sm-5 col-lg-2 col-xl-2 pad-right">
<label>Quantity:</label>
<br>
<input type="text" ng-model="expense.quantity" class="form-control" name="quantity" placeholder="5">
</div>
<div class="form-group col-sm-5 col-lg-2 col-xl-2 pad-right">
<label>Labor Rate:</label>
<br>
<input type="text" ng-model="expense.labor" class="form-control" name="labor" placeholder="20.00">
</div>
<div class="form-group col-sm-5 col-lg-2 col-xl-2 pad-right">
<label>Hours:</label>
<br>
<input type="text" ng-model="expense.hours" class="form-control" name="hours" placeholder="4">
</div>
<div class="form-group col-sm-5 col-lg-3 col-xl-2 pad-right">
<label>Responsible:</label>
<br>
<span>Renter</span>
<input type="radio" name="radio-1">
<span>Owner</span>
<input type="radio" name="radio-1">
</div>
<br>
<div class="col-sm-12 pad-right">
<span class="pad-right">Owner Total: {{ownerTotal}}</span>
<span class="pad-right">Renter Total: {{renterTotal}}</span>
</div>
<div class="col-sm-12 pad-right">
<button class="btn btn-primary btn-sm" ng-click="addExpense()"><i class="fa-check"></i>Add New Expense</button>
<button class="btn btn-primary btn-sm" ng-click="removeExpense($event)"><i class="fa-remove"></i>Remove Expense</button>
</div>
</li>
I have an array, an add method, and a remove method.
$scope.lineItems = [
{expense: 1}
];
//when button is clicked
//add a new blank object to the lineItems array
$scope.addExpense = function() {
var num = Math.random();
var item = {expense: num};
$scope.lineItems.push(item);
};
//when remove button is clicked
//remove the specific item that was clicked from the array
$scope.removeExpense = function($event) {
var elm = $event.currentTarget.parentElement.parentElement;
console.log(elm);
elm.remove();
//need to splice selected item OUT of the array
var i = ???
$scope.lineItems.splice(i, 1);
};
I've tried several things here. Most of the answers I've found just use indexOf, however the items are being dynamically generated by my model. So I don't know how to get an index of something that doesn't exist yet.
I've also tried some jQueryLite. I would love to just use something like : when $this is clicked, remove it from the dom. I can't seem to find the ANGULAR answer for that.
Instead of ng-click="removeExpense($event)" simply pass the lineItem, like ng-click="removeExpense(lineItem)". You can then find the lineItem in lineItems by indexOf
$scope.removeExpense = function(lineItem) {
var index = $scope.lineItems.indexOf(lineItem);
$scope.lineItems.splice(index, 1);
}
call removeExpense($index) on ng-click like:
<button class="btn btn-primary btn-sm" ng-click="removeExpense($index)"><i class="fa-remove"></i>Remove Expense</button>
and replace remove function with this code:
$scope.removeExpense = function(index) {
$scope.lineItems.splice(index, 1);
}

Clone row of elements in AngularJS

I have this Angular form http://plnkr.co/edit/?p=streamer&s=ph0QHW513czywawl.
I need to clone the row on clicking ADD (+) and delete selected row on clicking DELETE (-).
Looking for a solution in AngularJS only. In current solution, the scopes are not working correctly. Also did not yet figure out how to implement (-) functionality.
index.html
<div ng-controller="MyCtrl" style="padding: 10px;">
<br/>
<div style="width: 90%; display: inline-block; border: 1px silver solid;">
<div class="row">
<div class="col-xs-3">
<select class="form-control" data-ng-model="hr.langauge.level" tooltip="Level">
<option value="Native" ng-selected="true">Native</option>
</select>
</div>
<div class="col-xs-4">
<select class="form-control" data-ng-model="hr.langauge.name" tooltip="Language">
<option value="">Language</option>
<option value="EN">English</option>
<option value="IT">Italian</option>
<option value="DE">German</option>
<option value="FR">French</option>
</select>
</div>
<div class="col-xs-3">
<input type="text" data-ng-model="hr.langauge.remark" class="form-control" placeholder="Remark" tooltip="Remark">
</div>
<div class="col-xs-2">
</div>
</div>
<div select-last ng-repeat='item in items'></div>
</div>
<a class="btn" style="margin-bottom: 27px;" href="#" tooltip="Add" ng-click='addRow()'>
<i class="glyphicon glyphicon-plus"></i>
</a>
{{hr.langauge | json}}
language.html
<div class="row" style="padding-top: 5px;">
<div class="col-xs-3">
<select class="form-control" data-ng-model="hr.langauge.level" tooltip="Level">
<option value="">Level</option>
<option value="proficient">Proficient</option>
<option value="intermediate">Intermediate</option>
<option value="beginner">Beginner</option>
</select>
</div>
<div class="col-xs-4">
<select class="form-control" data-ng-model="hr.langauge.name" tooltip="Language">
<option value="">Language</option>
<option value="EN">English</option>
<option value="IT">Italian</option>
<option value="DE">German</option>
<option value="FR">French</option>
</select>
</div>
<div class="col-xs-3">
<input type="text" data-ng-model="hr.langauge.remark" class="form-control" placeholder="Remark" tooltip="Remarks">
</div>
<div class="col-xs-2">
<a class="btn" href="#" tooltip="Delete" ng-click="deleteRow({{$index}});">
<i class="glyphicon glyphicon-minus"></i>
</a>{{$index}}
</div>
</div>
script.js
var myApp = angular.module('myApp',[]);
myApp.directive('selectLast', function () {
return {
restrict: 'A',
templateUrl: 'language.html'
}
});
function MyCtrl($scope) {
$scope.items = [];
$scope.newitem = '';
$scope.addRow = function(){
$scope.items.push($scope.newitem);
console.log('+ clicked');
}
$scope.deleteRow = function(rowNo) {
/*$scope.items.splice($scope.newitem);*/
console.log('- clicked in row ' + rowNo);
}
}
Based on your comment and plunker, it looks like you have the Add figured out. The remove row is easier. All you need to do is splice out the row. The issue on your view is you have the index surrounded by {{}} which isn't necessary.
$scope.deleteRow = function(rowNo) {
/*$scope.items.splice($scope.newitem);*/
$scope.languages.splice(rowNo, 1);
console.log('- clicked in row ' + rowNo);
};
<a class="btn" href="#" tooltip="Delete" ng-click="deleteRow($index);">
<i class="glyphicon glyphicon-minus"></i>
</a>{{$index}}
Here is an updated plunker: http://plnkr.co/edit/7vW24aDyZH02LO1iO7F3?p=preview&s=ph0QHW513czywawl
functionality is to have a click edit a row entry, create a temporary copy of the row data, then update.
Below link
https://thinkster.io/egghead/angular-copy/

Resources