Unable to pass dynamic form inputs to the controller function - angularjs

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.

Related

close bootstrap modal window using angularjs after submit

I'm creating an inventory app, and the user has the option to add a new product or edit an existing one. Both options bring up the same modal window, and I want it to close automatically after the user clicks on submit.
Below is part of my code, my entire code is here: http://codepen.io/andresq820/pen/LWGKXW
HTML
<div class="modal fade" id="editItemModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">{{title(item.code)}}</h4>
</div>
<div class="modal-body">
<form name="myEditForm" ng-submit="editProduct(item)">
<div class="form-group">
<label for="code">Code:</label>
<input type="text" size="5" maxlength="5" minlength="3" class="form-control" name="code" id="code"
ng-model="item.code" ng-disabled="false" ng-pattern="/^[a-zA-Z0-9]*$/">
<span ng-show="myEditForm.code.$error.pattern">Code can only be alphanumeric.</span> </br>
<span ng-show="myEditForm.code.$error.minlength">Code has to be at least 3 characters</span>
</div>
<div class="form-group">
<label for="description">Description:</label>
<input type="text" class="form-control" name="description" id="description" ng-model="item.description" required>
<span ng-show="myEditForm.description.$touched && myEditForm.description.$invalid">The description is required.</span>
</div>
<div class="form-group">
<label for="amount">Amount:</label>
<input type="number" class="form-control" name="amount" id="amount" size="5" maxlength="5"
ng-model="item.amount" ng-pattern="/^[0-9]{1,7}$/">
<span ng-show="myEditForm.amount.$error.pattern">Only whole numbers are allowed</span>
</div>
<div class="form-group">
<label for="newImage">{{loadImg}}</label>
<input type="file" class="form-control" name="newImage" id="newImage" ng-model="item.image">
</div>
<div class="form-group" ng-show="displayRadioBtns">
<label for="radio">Type:</label>
<div class="radio">
<label><input type="radio" name="optradio" ng-model="item.type" value="in">In</label>
<label><input type="radio" name="optradio" ng-model="item.type" value="out">Out</label>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Close" />
<input type="submit" class="btn btn-primary pull-right" value="Submit" ng-disabled="myEditForm.$invalid"/>
</div>
</form>
</div>
</div>
</div>
</div>
ANGULARJS
$scope.editProduct = function(item){
var index = $scope.items.indexOf(item);
console.log(index);
console.log(item);
console.log(item.code.valueOf());
if(index == -1){
console.log('new item');
$scope.item.code = item.code;
$scope.item.description = item.description;
$scope.item.in = item.amount;
$scope.item.out = 0;
$scope.item.createdOn = Date.now();
$scope.items.push($scope.item);
$scope.item = {};
}else{
console.log('edit item');
console.log(item);
console.log(item.type);
console.log($scope.item.type);
console.log(index);
$scope.items[index].code = item.code;
console.log($scope.items[index].code);
$scope.items[index].description = item.description;
console.log($scope.items[index].description);
$scope.items[index].image = item.image;
if($scope.item.type == 'in'){
console.log($scope.item.type);
console.log(typeof($scope.items[index].in));
console.log(typeof($scope.item.amount));
console.log(typeof(item.amount));
$scope.items[index].in += item.amount;
console.log($scope.items[index].in);
$scope.item = {};
}else if($scope.item.type == 'out'){
console.log($scope.item.type);
$scope.items[index].out += $scope.item.amount;
$scope.item = {};
}else{
alert("Type is a required field");
return;
};
}
};
You can make function calls on ngSubmit
form class="well" (ngSubmit)="addUserModal.hide(); addUser(model); userForm.reset()" #userForm="ngForm"
I haven't used AngularJS, but the following works for me in Angular 2, if you're able to use jQuery:
$(".modal").modal("hide")
Fire button click on submit event in angularJS.
<input id="quemodalcancel" type="submit" value="Cancel" class="btn blue_btn" data-dismiss="modal" aria-hidden="true">
$scope.editProduct = function(item){
// submit button code
document.querySelector('#quemodalcancel').click();
}

watching on the select item in 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..

Issue with angular radio input not populating the model when clicked

I have a strange issue with a radio input not populating the model of an angular form.
All fields populate the model except for the radio input...
The radio input is given at the beginning of the form below. I use ng-inspector and I can see that signupForm.member.role does not get populated when I click one of the radio values.
Can someone please help?
<form name="formCtrl" ng-submit="signup(formCtrl)" class="col-xs-12" novalidate role="form">
<h4>{{'SIGNUP_FORM_ROLE_PREFIX' | translate}}</h4>
<div class="btn-group Choix col-xs-12 text-center" data-toggle="buttons" ng-class="getCssClasses(formCtrl, formCtrl.signupRole)">
<label class="btn StateButton col-xs-6">
<img class="img-responsive" src="assets/media/img/parents.svg" />
<input type="radio" name="signupRole" ng-model="signupForm.member.role" value="ROLE_BASIC_PARENTS" ng-required="true" />
<span class="help-block">{{'DOMAIN_ENUM_' + 'ROLE_BASIC_PARENTS' | translate}}</span>
</label>
<label class="btn StateButton col-xs-6">
<img class="img-responsive" src="assets/media/img/professionel.svg" />
<input type="radio" name="signupRole" ng-model="signupForm.member.role" value="ROLE_BASIC_CHILDCARE_WORKER" ng-required="true" />
<span class="help-block">{{'DOMAIN_ENUM_' + 'ROLE_BASIC_CHILDCARE_WORKER' | translate}}</span>
</label>
<div ng-messages="formCtrl.signupRole.$error" ng-if="formCtrl.$submitted">
<div ng-message="required" class="control-label">{{'SIGNUP_FORM_ROLE_REQUIRED'| translate}}</div>
</div>
</div>
<hr>
<div class="form-group" ng-class="getCssClasses(formCtrl, formCtrl.firstName)">
<div class="input-group">
<span class="input-group-addon">
<span class="glyphicon icon-Prenom" aria-hidden="true"></span>
</span>
<input type="text" name="firstName" ng-minlength="2" placeholder="{{'SIGNUP_FORM_FIRST_NAME' | translate}}" ng-model="signupForm.member.firstName" ng-required="true" class="form-control" />
<span ng-if="isSuccessFeedback(formCtrl, formCtrl.firstName)" class="form-control-feedback" aria-hidden="true"><span class="glyphicon icon-Valid" aria-hidden="true"></span></span>
<span ng-if="isErrorFeedback(formCtrl, formCtrl.firstName)" class="form-control-feedback" aria-hidden="true"><span class="glyphicon icon-Erreur" aria-hidden="true"></span></span>
</div>
<div ng-messages="formCtrl.firstName.$error" ng-if="formCtrl.$submitted">
<div ng-message="required" class="control-label">{{'SIGNUP_FORM_FIRST_NAME_REQUIRED' | translate}}</div>
<div ng-message="minlength" class="control-label">{{'SIGNUP_FORM_FIRST_NAME_REQUIRED' | translate }}</div>
</div>
</div>
</form>
Here is a working plunker: http://plnkr.co/edit/lsaevbL0mBRku7zcrGDJ
One can notice that the radio is not taken into account when the form is submitted even if one of the radios is selected...
Simply use value instead of ng-value. Please see this working demo: http://plnkr.co/edit/2EB4NvTO1StN50NIXOyn?p=preview.
You should not use ng-value, which is looking for $scope.ROLE_BASIC_PARENTS.
Check AngularJS.org, the example there use:
<input type="radio" ng-model="color.name" ng-value="specialValue">
And in the controller:
$scope.specialValue = {
"id": "12345",
"value": "green"
};

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);
}

Set a form input to dirty in angularjs?

I have a form that I auto input the current date into an input field. I want to set the input field to dirty because when it tries to sync with firebase, that input field is not included unless you interact with it.
I have tried the following in many different forms...and I am at a loss.
var now = new Date();
$scope.load = function () {
if (!$rootScope.auth) {
$location.path('/a/');
} else {
$scope.logs = Logs.list($scope);
$scope.newDate = now;
$scope.logForm.$setDirty(true);
}
};
<form name="logForm" novalidate class="css-form">
<div class="form-group input-group">
<input class="form-control" name="action" placeholder="Action" type="text" value="{{newAction}}" ng-model="newAction" required />
<div class="input-group-addon">
<i class="fa fa-rocket"></i>
</div>
</div>
<div class="form-group input-group">
<input class="form-control" name="quantity" placeholder="Quantity" type="number" value="{{newQuantity}}" ng-model="newQuantity" ng-pattern="/^[0-9]*$/" />
<div class="input-group-addon">
<i class="fa fa-plus-square"></i>
</div>
</div>
<div class="form-group input-group">
<input class="form-control" name="location" placeholder="Location" type="text" value="{{newLocation}}" ng-model="newLocation" />
<div class="input-group-addon">
<i class="fa fa-map-marker"></i>
</div>
</div>
<div class="form-group input-group">
<input class="form-control" name="date" placeholder="Date" type="datetime" value="{{newDate}}" ng-model="newDate" />
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
</div>
<button class="btn btn-info btn-block" ng-click="create()">Add log</button>
</form>
The form tag creates its own scope, so to have a reliable scope structure, we shouldn't use primitives for the ng-model values.
To ensure, that we have access to the form controller, we have to delay the form initialization into the next digest cycle. This is achieved with the use of the $timeout service.
http://jsbin.com/OvIvIHO/3/
jsbin contains the updated version

Resources