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

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

Related

Save values of dynamically created input

I'm trying to save my input data into modulo.descripcion. But it doesn't work. I just get back the initial values, not the new ones.
HTML
<div class="row">
<div class="form-group col-md-10">
<label for="codigoInput" class="control-label">Descripción</label>
<button type="button" onclick="addFields()" class="btn btn-default btn-sm" style="margin-bottom: 5px">Agregar campos</button>
<input style="margin-bottom: 3px" type="text" class="form-control input-sm" next-focus tabindex="0" placeholder="Escribe una característica del módulo" ng-repeat="d in modulo.descripcion" ng-model="d">
<small class="help-block with-errors desc"></small>
</div>
</div>
<a ng-click="saveEdit(modulo)" class="btn btn-success btn-sm">Guardar</a>
JS
function addFields() {
var set = $('.desc');
var length = set.length-1;
$('<input style="margin-bottom: 3px" type="text" class="form-control input-sm" next-focus tabindex="0" placeholder="Escribe una característica del módulo" ng-model="d">').insertBefore($('small.desc'));
}
The best way is to insert a new object to modulo.descripcion array, that way the repeat will automatically populate the input, and you can also add the new item as an ng-model.
like that:
$scope.addField = function(){
modulo.descripcion.push({type:'number', value=''})
}

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

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.

bootstrap "control-label" behaves strange when following dynamically created list

<!-- code snippet of html -->
<div class="form-group">
<label for="items" class="col-sm-2 control-label">Items</label>
<div class="pull-left input-group">
<input type="text" class="form-control" ng-model="name">
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="addNewItem()">Add</button>
</span>
</div>
<div>
<ul class="pull-left">
<li ng-repeat="item in items">
<p style="display: inline-block">{{item}}</p>
<button type="button" class="btn btn-default" ng-click="deleteItem(item)">Delete</button>
</li>
</ul>
</div>
</div>
<div class="form-group">
<label for="anotherField" class="col-sm-2 control-label">Another Field</label>
<input type="text" class="form-control" ng-model="anotherField" id="anotherField">
</div>
/* code snippet in Augular controller */
$scope.addNewItem = function() {
if ($scope.name && $scope.name.trim()) {
if ($scope.items.indexOf($scope.name.trim()) >= 0) {
console.log('item name should not be duplicated');
} else {
$scope.items.push($scope.name.trim());
$scope.name = '';
}
}
};
$scope.deleteItem = function(item) {
var idx = $scope.items.indexOf(item);
if (idx >= 0) $scope.items.splice(idx, 1);
};
Above codes function properly, but the only problem is that when I create even on one new item, the label supposedly for "anotherField" just shows up immediately after this this very item (even misaligned with the label for "items"); when more items were created, it's simply placed at the end of the 1st item but not like a label for "anotherField" any more. Anybody can help to address this "strange" style issue?
Thanks,
Xihua

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..

Resources