I now try to make Items list form that are able to add, edit and delete.
Add and edit are work fine, however, when I trying to delete it is not working as expected.
Here, is my partial of my code, that consist of delete button.
<!-- Added Items Stage -->
<div ng-repeat-start="item in items" ng-form="editItemForm" class="row">
<div class="col">
<input type="text" name="description" ng-model="item.description" placeholder="description" required>
</div>
<div class="col">
<input type="number" name="quantity" pattern="\d*" ng-model="item.quantity" placeholder="quantity" required>
</div>
<div class="col">
<input type="text" name="price" ng-model="item.price" placeholder="price" required>
</div>
<div class="col">
<select name="taxType" ng-model="item.taxType" required>
<option value="ZR">ZR</option>
<option value="SR">SR</option>
</select>
</div>
<div class="col col-20" ng-bind="(item.quantity&&item.price)?((item.quantity*item.price) | currency:''):'0.00'"></div>
<div class="col col-10">
<button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem(item)"></button>
</div>
</div>
<hr ng-repeat-end>
Second part is how I delete item
$scope.deleteItem = function(item) {
$scope.items.splice($scope.items.indexOf(item), 1);
};
I tried pass in $index, or use delete instead of splice, but it still cannot work. Help me please. Thank you.
This is my demo
Note: I think the item removed, but the html not updated.
That sometimes happens when Angular is not aware that a change has been made to the model. When that's the case you can force an update by wrapping your function inside a $timeout with no delay:
$scope.deleteItem = function(item) {
$timeout(function () {
$scope.items.splice($scope.items.indexOf(item), 1);
});
};
Don't forget to inject the $timeout service into the controller.
I not quite understand why? but your problem in ng-form attribute on your repeater.
If you remove it - all work
var nameApp = angular.module('starter', ['ionic', 'ngMessages']);
nameApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: 'auth.html',
})
.state('home', {
url: '/home',
templateUrl: 'home.html',
controller: 'HomeCtrl'
});
$urlRouterProvider.otherwise("/auth");
});
nameApp.directive('isolateForm', [function() {
return {
restrict: 'A',
require: '?form',
link: function(scope, elm, attrs, ctrl) {
if (!ctrl) {
return;
}
// Do a copy of the controller
var ctrlCopy = {};
angular.copy(ctrl, ctrlCopy);
// Get the parent of the form
var parent = elm.parent().controller('form');
// Remove parent link to the controller
parent.$removeControl(ctrl);
// Replace form controller with a "isolated form"
var isolatedFormCtrl = {
$setValidity: function(validationToken, isValid, control) {
ctrlCopy.$setValidity(validationToken, isValid, control);
parent.$setValidity(validationToken, true, ctrl);
},
$setDirty: function() {
elm.removeClass('ng-pristine').addClass('ng-dirty');
ctrl.$dirty = true;
ctrl.$pristine = false;
},
};
angular.extend(ctrl, isolatedFormCtrl);
}
};
}]);
nameApp.controller('AuthCtrl', function($scope, $state) {
$scope.newItem = {
description: undefined,
quantity: undefined,
price: undefined,
taxType: undefined
};
$scope.items = [];
$scope.addItem = function() {
console.log({
description: $scope.newItem.description,
quantity: $scope.newItem.quantity,
price: $scope.newItem.price,
taxType: $scope.newItem.taxType
});
$scope.items.push({
description: $scope.newItem.description,
quantity: $scope.newItem.quantity,
price: $scope.newItem.price,
taxType: $scope.newItem.taxType
});
console.log($scope.items);
$scope.newItem.description = undefined;
$scope.newItem.quantity = undefined;
$scope.newItem.price = undefined;
$scope.newItem.taxType = "SR";
};
$scope.deleteItem = function(item) {
$scope.items.splice($scope.items.indexOf(item), 1);
};
$scope.authorization = {
referenceNo: '',
};
$scope.signIn = function(form) {
if (form.$valid) {
$state.go('home');
}
};
});
nameApp.controller('HomeCtrl', function($scope) {
});
.error-container {
margin: 5px 0;
}
.error-container:last-child {
margin: 5px 0 0;
}
.error {
padding: 10px 16px;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 11px;
text-transform: uppercase;
color: #555;
vertical-align: middle;
}
.error i {
font-size: 24px;
color: #B83E2C;
vertical-align: middle;
}
.last-error-container > .error {
padding: 10px 16px 0;
}
.has-errors {
border-bottom: 3px solid #B83E2C;
}
.no-errors {
border-bottom: 3px solid green;
}
<html ng-app="starter">
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>
<ion-nav-bar class="bar-positive">
<ion-nav-back-button class="button-clear">
<i class="ion-arrow-left-c"></i> Back
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
<script id="auth.html" type="text/ng-template">
<ion-view view-title="Authorization Page">
<ion-content class="padding" ng-controller="AuthCtrl">
<h2 style="text-align: center;">Form validation example</h2><br/>
<form name="newDocumentForm" ng-submit="signIn(newDocumentForm)" novalidate>
<div class="list">
<label class="item item-input" ng-class="{ 'has-errors' : newDocumentForm.referenceNo.$invalid && newDocumentForm.$submitted, 'no-errors' : newDocumentForm.referenceNo.$valid && newDocumentForm.$submitted}">
<span class="input-label">Reference No</span>
<input type="text" name="referenceNo" ng-model="authorization.username" ng-minlength="5" ng-maxlength="20" required>
</label>
<div class="error-container" ng-show="newDocumentForm.referenceNo.$error && newDocumentForm.$submitted" ng-messages="newDocumentForm.referenceNo.$error">
<div ng-messages-include="error-list.html"></div>
</div>
</div>
<!-- Title -->
<div class="row">
<div class="col">Description</div>
<div class="col">Quantity</div>
<div class="col">Price</div>
<div class="col">Tax Type</div>
<div class="col col-20">Amount</div>
<div class="col col-10"></div>
</div>
<!-- Added Items Stage -->
<div ng-repeat-start="item in items" class="row">
<div class="col">
<input type="text" name="description" ng-model="item.description" placeholder="description" required>
</div>
<div class="col">
<input type="number" name="quantity" pattern="\d*" ng-model="item.quantity" placeholder="quantity" required>
</div>
<div class="col">
<input type="text" name="price" ng-model="item.price" placeholder="price" required>
</div>
<div class="col">
<select name="taxType" ng-model="item.taxType" required>
<option value="ZR">ZR</option>
<option value="SR">SR</option>
</select>
</div>
<div class="col col-20" ng-bind="(item.quantity&&item.price)?((item.quantity*item.price) | currency:''):'0.00'"></div>
<div class="col col-10">
<button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem(item)"></button>
</div>
</div>
<hr ng-repeat-end>
<!-- Adding Stage -->
<div ng-form="addItemForm" class="row" isolate-form>
<div class="col">
<input type="text" name="description" ng-model="newItem.description" placeholder="description" required/>
</div>
<div class="col">
<input type="number" pattern="\d*" name="quantity" ng-model="newItem.quantity" placeholder="quantity" required/>
</div>
<div class="col">
<!--<input type="text" name="price" ng-model="newItem.price" placeholder="price" ng-pattern="/^[0-9]{1,7}$/" required/>-->
<input type="text" name="price" ng-model="newItem.price" placeholder="price" step="0.01" ng-pattern="/^[0-9]+(\.[0-9]{1,2})?$/" required/>
</div>
<div class="col">
<select name="taxType" ng-model="newItem.taxType" required>
<option value="ZR">ZR</option>
<option value="SR">SR</option>
</select>
</div>
<div class="col col-20" ng-bind="(newItem.quantity&&newItem.price)?((newItem.quantity*newItem.price) | currency:''):'0.00'"></div>
<div class="col col-10">
<button type="button" ng-disabled="addItemForm.$invalid" class="button button-balanced button-clear icon ion-plus-circled" ng-click="addItem()"></button>
</div>
</div>
<div class="error-container last-error-container" ng-show="addItemForm.price.$error.pattern" ng-messages="addItemForm.price.$error">
<div ng-messages-include="currency-error-list.html"></div>
</div>
<button class="button button-full button-positive" type="submit">
Submit
</button>
</form>
</ion-content>
</ion-view>
</script>
<script id="home.html" type="text/ng-template">
<ion-view view-title="Second page">
<ion-content class="padding">
<h1>Wellcome</h1>
</ion-content>
</ion-view>
</script>
<script id="currency-error-list.html" type="text/ng-template">
<div class="error" ng-message="pattern">
<i class="ion-information-circled"></i>
Invalid currency format!
</div>
</script>
<script id="error-list.html" type="text/ng-template">
<div class="error" ng-message="required">
<i class="ion-information-circled"></i>
This field is required!
</div>
<div class="error" ng-message="minlength">
<i class="ion-information-circled"></i>
Minimum length of this field is 5 characters!
</div>
<div class="error" ng-message="maxlength">
<i class="ion-information-circled"></i>
Maximum length of this field is 20 characters!
</div>
</script>
Came across the same problem; “Splice not working”. In my case, I had to resolve as below just in case if it helps someone.
If you are dealing with objects, please note 'indexOf' works for array not for Object inside the array. You can do something like below to identify the index and handle this case;
$scope.removeReport = function(report) {
var index = $scope.contact.reports.map(function(r) { return r.id;}).indexOf(report.id);
if (index >= 0) {
$scope.contact.reports.splice(index, 1);
}
}
Use Index in place of Item
<button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem($index)"></button>
Also in Controller
$scope.deleteItem = function(index) {
$scope.items.splice(index, 1);
};
Related
I don't know the reason why, but at each of page of my webapp, at the left side upper there is a dot like this:
It's an html problem I think, in fact running the snippet below you can see that:
<ion-view view-title="Invia feedback">
<ion-content class="ioncontentcatalog">
<li>
<h2 class="sub-header" style="color:#4e67c3;" ng-if=logged>Invia feedback</h2>
<h2 class="sub-header" style="color:#4e67c3;" ng-if=!logged>Per poter mandare un feedback devi registrarti!</h2>
<form name="feedback">
<div class="list" ng-if=logged>
<label class="item item-input">
<textarea name="Text1" cols="40" rows="5" ng-model="feedbacktext" required></textarea>
</label>
<label ng-show="feedback.$invalid"> Scrivi qualcosa </label>
<label class="item">
<button class="button button-block button-positive" ng-disabled="feedback.$invalid" ng-click="send(feedbacktext)">Invia</button>
</label>
</div>
</form>
</li>
</ion-content>
</ion-view>
However, I put also the controller of this page:
.controller('SendFeedbackCtrl', function($scope, $stateParams, $ionicPopup, restService) {
var token = localStorage.getItem("token");
$scope.tknuser = JSON.parse(token);
$scope.logged = false;
$scope.feedbackform = {
message: "adad",
readfb: false,
user: {
iduser: -1
}
};
And also the class style used:
.ioncontentcatalog {
background-image: url('../img/background.png')
}
That's very strange and I don't know how to solve.
It is the li default style, add this CSS rule to remove it:
list-style
https://developer.mozilla.org/en/docs/Web/CSS/list-style
.ioncontentcatalog li{
list-style: none;
}
<ion-view view-title="Invia feedback">
<ion-content class="ioncontentcatalog">
<li>
<h2 class="sub-header" style="color:#4e67c3;" ng-if=logged>Invia feedback</h2>
<h2 class="sub-header" style="color:#4e67c3;" ng-if=!logged>Per poter mandare un feedback devi registrarti!</h2>
<form name="feedback">
<div class="list" ng-if=logged>
<label class="item item-input">
<textarea name="Text1" cols="40" rows="5" ng-model="feedbacktext" required></textarea>
</label>
<label ng-show="feedback.$invalid"> Scrivi qualcosa </label>
<label class="item">
<button class="button button-block button-positive" ng-disabled="feedback.$invalid" ng-click="send(feedbacktext)">Invia</button>
</label>
</div>
</form>
</li>
</ion-content>
</ion-view>
Just remove li decoration like this:
<li style="list-style-type: none;">
I have a submit button on my form but for some weird reason it requires me to click on the button twice before it calls the save function underneth, I am using Pug for my HTML
Here is my HTML template:
<form ng-submit="save()">
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<ol ng-model="service.category" title="Select a category" class="nya-bs-select">
<li nya-bs-option="category in categories.rows" class="nya-bs-option"><a> <span>{{category.name}} </span><span class="glyphicon glyphicon-ok check-mark"></span></a></li>
</ol>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<div class="input-group"><span class="input-group-addon">Service Name</span>
<input type="text" ng-model="service.name" class="form-control"/>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<textarea ng-model="service.description" placeholder="Service Description" rows="10" class="form-control"></textarea>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<button type="submit" value="Save" class="btn btn-default"> Save</button>
</div>
</div>
</div>
</form>
The save function called is as
angular.module('App.controllers')
.controller('UpdateServiceCtrl', [
'$scope', '$state', 'ServicesService', 'Notification',
function ($scope, $state, ServicesService, Notification) {
$scope.service = $scope.$parent.service;
$scope.categories = $scope.$parent.categories;
/**
* Edits a service
* #param {integer} serviceID Id of the service to be edited
* #return {undefined} Does not return any values
*/
$scope.save = function () {
$scope.service.category_id = $scope.service.category.id;
ServicesService.save($scope.service, $scope.service.id)
.then(function (result) {
$state.reload();
})
}
}]);
You can disable the submit button after it clicked first time using
ng-disabled='isButtonEnabled' your html.
Modify your save like this
$scope.save = function () {
$scope.isButtonEnabled = false;
$scope.service.category_id = $scope.service.category.id;
ServicesService.save($scope.service, $scope.service.id)
.then(function (result) {
$state.reload();
})
}
Let me know if it doesn't works.
My angularJS push option is not working. Could someone please tell me where I'm going wrong and a fix for it, please? I started learning this language only for a week now. Please excuse me if the error/mistake is silly.
Thank you
<body ng-app="app" ng-controller ="Ctrl" >
<style>
.alert{
color: crimson;
font-size: 19px;
}
.form{
width: 72%;
margin-left: 12%;
border: 2px solid gold;
}
</style>
<script>
var app = angular.module("app", []);
app.controller("Ctrl", function ($scope) {
$scope.main = [{"ngmail": "a.vanhala#evil.com", "pass": "thor", "cpass": "thor"}];
$scope.add = function ($scope) {
$scope.main.push($scope.sf);
};
});
</script>
<div>
<div>
<form name="regform" class="form-horizontal" role="form" style=" margin: auto;" >
<div class="form-group">
<label class="control-label col-sm-2" for="email3">Email:</label>
<div class="col-sm-4">
<input type="email" class="form-control" placeholder="Enter email" id="email3" name="email" ng-model="sf.ngmail" required/>
<span class ="alert" ng-show=" regform.email.$touched && regform.email.$error.required"> Required</span>
<span class ="alert" ng-show=" !regform.email.$error.required && (regform.email.$touched && regform.email.$invalid)"> Invalid Email</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="pwd3">Password:</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="pwd3" placeholder="Enter password" ng-model="sf.pass" name="password" required/>
<span class ="alert" ng-show=" regform.password.$touched && regform.password.$error.required"> Required</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="pwd4">Confirm password:</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="pwd3" placeholder="Enter password" ng-model="sf.cpass" name="cpassword" required/>
<span class ="alert" ng-show=" regform.cpassword.$touched && regform.cpassword.$error.required"> Required</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox"> Remember me</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" ng-click="add()" class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
</div>
<br>
<div>
<table border="1">
<thead>
<tr>
<th>Email</th>
<th>password</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="m in main">
<td>{{m.ngmail}}</td>
<td>{{m.pass}}</td>
</tr>
</tbody>
</table>
</div>
</body>
As you are using $scope in function parameter, which is killing the existence of $scope dependency of controller & created a new variable with name $scope. You shouldn't need to add $scope inside your function, it would be already available inside your function.
Code
$scope.add = function () {
$scope.main.push($scope.sf);
};
You don't need to pass $scope in function .
Try like this
$scope.add = function () {
$scope.main.push($scope.sf);
};
have you tried push method without passing the scope to the function
$scope.add= function(){ // no scope here
$scope.main.push($scope.sf);
};
I'm trying to load a modal with Angular and then fill it with a template.
The problem is that the inputs are overshooting the modal - here is a screenshot of the problem:
Here is the code for the modal instantiation:
$scope.logInOpen = function () {
console.log($modal);
var modalInstance = $modal.open({
templateUrl: '../views/login.html',
controller: 'AuthController',
size: 'sm'
});
modalInstance.result.then(function () {
console.log($scope.modalInstance);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
$scope.modalInstance = null;
});
}
and here is the /view/login.html
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-2">
<form ng-submit="logIn()" style="margin-top:30px;">
<h3>Log In</h3>
<div class="form-group">
<input type="text"
class="form-control"
placeholder="Email"
ng-model="user.username"></input>
</div>
<div class="form-group">
<input type="password"
class="form-control"
placeholder="Password"
ng-model="user.password"></input>
</div>
<button type="submit" class="btn btn-success">Log In</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<span ><small> Forgot Password</small></span>
</form>
<div class="row">
<div ng-show="error" class="alert alert-danger">
<span>{{ error.message }}</span>
</div>
</div>
</br><br>
</div><!-- closes .col-md-6 -->
</div><!-- closes .row -->
</div><!-- closes .container -->
It's because you have them in a modal - in a .container. Try removing the .container class from the modal.
.container has static widths and not percentages. This is why it's overflowing.
hi i want to clear the form values after successfull completion. Houw should i implemnt
<div ng-controller="employeelistController as listControl">
<div class="container form-group" ng-controller="addEmployee as addemp">
<form name="frmEmployee" ng-submit="Add(addemp.employee) && frmEmpbloyee.$valid">
<div class="col-lg-4 ctrmain">
<div class="row">
<div class="col-lg-6">
<strong>Employee No</strong>
</div>
<div class="col-lg-6">
<input type="number" id="txtEmpId" ng-model="addemp.employee.employeeid" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>FirstName</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtfirstName" ng-model="addemp.employee.firstname" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>LastName</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtlastName" ng-model="addemp.employee.lastname" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>Department</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtDept" ng-model="addemp.employee.department" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>DOB</strong>
</div>
<div class="col-lg-6">
<input type="date" id="DTdob" ng-model="addemp.employee.dateofbirth" required class="form-control" />
</div>
</div>
<div class="row">
<input type="submit" id="btnSubmit" class="btn btn-primary value=" save" />
</div>
</div>
which is the best way to implement this. I have tried many ways. please help.
$scope.Add = function (emp,$scope) {
this.EmployeeObject = angular.copy(emp);
employee.push(this.EmployeeObject);
$scope.emp = null;
}
which is the best way to implement this. I have tried many ways. please help.
First of all you don't need $scope in the argument of the Add function.
$scope.Add = function (emp) {
this.EmployeeObject = angular.copy(emp);
employees.push(this.EmployeeObject);
this.employee=null;
$scope.$setPristine(true);
}
update it with the demo
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $compile) {
'use strict';
$scope.empList = [];
$scope.addemp = {};
$scope.saveEmp = function(){
$scope.empList.push($scope.addemp);
$scope.reset();
};
$scope.reset = function() {
$scope.addemp = {};
$scope.form.$setPristine();
}
});
input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
input.ng-valid.ng-dirty {
background-color: #78FA89;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainCtrl">
<form name="form" id="form" novalidate ng-submit="saveEmp()">
<div class="row">
<div class="col-lg-6">
<strong>Employee No</strong>
</div>
<div class="col-lg-6">
<input type="number" id="txtEmpId" ng-model="addemp.employeeid" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>FirstName</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtfirstName" ng-model="addemp.firstname" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>LastName</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtlastName" ng-model="addemp.lastname" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>Department</strong>
</div>
<div class="col-lg-6">
<input type="text" id="txtDept" ng-model="addemp.department" required class="form-control" />
</div>
</div>
<div class="row">
<div class="col-lg-6">
<strong>DOB</strong>
</div>
<div class="col-lg-6">
<input type="date" id="DTdob" ng-model="addemp.dateofbirth" required class="form-control" />
</div>
</div>
<div class="row">
<button type="submit" ng-disabled="form.$invalid ">submit</button>
<button type="reset" ng-disabled="form.$pristine" ng-click="reset()">reset</button>
</div>
</form>
<p>form: {{addemp | json}}</p>
<p>empList: {{empList | json}}</p>
<p>Pristine: {{form.$pristine}}</p>
<p> <pre>Errors: {{form.$error | json}}</pre>
</p>
</div></div>
$scope.Add = function (emp) {
this.EmployeeObject = angular.copy(emp);
employee.push(this.EmployeeObject);
$scope.emp = {}; // initialize the form to empty object
$scope.frmEmployee.$setPristine(); // set it to as user has not interacted with the form.
}
I have cleared textbox with below code. e.g I have cleared FirstName textbox.
HTML SECTION
<td ng-show="a">
<input type="text" ng-model="e.FirstName" />
</td>
Controller SECTION
e.FirstName= "";
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $compile) {
'use strict';
function resetform() {
document.getElementById("frmEmployee").reset();
}
$scope.Add = function (emp,$scope) {
this.EmployeeObject = angular.copy(emp);
employee.push(this.EmployeeObject);
resetform();
}
});
Its pure JavaScript with simple one line code.
document.getElementById('yourFormId').reset()
Add this syntax at the end of the function in controller after submitting the form.