angular form ng-repeat deleting single form - angularjs

i am working with dynamic forms with ng-repeat .i am getting dynamic forms according to my userid. each form has delete button. my requirement is once i am clicking delete button i need to delete that particular form and those values from my user obj and remaining values i need to send to server. in this example i want to delete id 2 (2nd form), and 1st and 2nd form data i need to store one variable.
please send some fiddle for this .
my html code
<div ng-app="myApp">
<div ng-controller="myCtrl">
<form role="form" name='userForm' novalidate>
<div class="container">
<div class="row" ng-repeat="user in users">
<div class="form-group">
<div class="col-md-3">
<label>ID</label>
<input ng-model="user.id" id="user.id" name="user.id" placeholder="Enter bugid" type="text" required readonly disabled>
</div>
<div class="col-md-3">
<label>Comments</label>
<textarea ng-model="user.comment" id="textarea1" rows="1" required></textarea>
</div>
<div class="col-md-3 ">
<label>Location</label>
<select ng-model="user.location" ng-options="v for v in locations" ng-init='initLocation(user)' name="select2" required>
</select>
</div>
<div>
<button>delete</button>
</div>
</div>
</div>
</div>
<div class="buttonContainer text-center btn-container">
<br>
<button ng-disabled="userForm.$invalid" type="button" id="adduser" ng-click="adduser()">Add user</button>
<button type="button" class="btn button--default btn--small pull-center">Close</button>
</div>
</form>
</div>
js file
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', function($scope, $timeout) {
$scope.ids = [1, 2, 3];
$scope.users = $scope.ids.map(function(id) {
return {
id: id,
comment: "",
location: ""
};
});
$scope.locations = ['india', 'usa', 'jermany', 'china', 'Dubai'];
$scope.initLocation = (user) => {
$timeout(() => {
user.location = $scope.locations[0];
});
}
$scope.adduser = function() {
var data = $scope.users.map(function(user) {
return {
"userid": user.id,
"manualcomment": user.comment,
"location": user.location
}
});
console.log("data", data)
}
});

As per your requirement i am adding ng-click to delete button and adding removeSelForm method and pass your user object into that function parameter. in controller i am removing that particular form values from users object.
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', function($scope, $timeout) {
$scope.ids = [1, 2, 3];
$scope.users = $scope.ids.map(function(id) {
return {
id: id,
comment: "",
location: ""
};
});
$scope.locations = ['india', 'usa', 'jermany', 'china', 'Dubai'];
$scope.initLocation = (user) => {
$timeout(() => {
user.location = $scope.locations[0];
});
}
$scope.removeSelForm = function(item) {
var index = $scope.users.indexOf(item)
$scope.users.splice(index, 1);
}
$scope.adduser = function() {
var data = $scope.users.map(function(user) {
return {
"userid": user.id,
"manualcomment": user.comment,
"location": user.location
}
});
console.log("data", data)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<form role="form" name='userForm' novalidate>
<div class="container">
<div class="row" ng-repeat="user in users">
<div class="form-group">
<div class="col-md-3">
<label>ID</label>
<input ng-model="user.id" id="user.id" name="user.id" placeholder="Enter bugid" type="text" required readonly disabled>
</div>
<div class="col-md-3">
<label>Comments</label>
<textarea ng-model="user.comment" id="textarea1" rows="1" required></textarea>
</div>
<div class="col-md-3 ">
<label>Location</label>
<select ng-model="user.location" ng-options="v for v in locations" ng-init='initLocation(user)' name="select2" required>
</select>
</div>
<div>
<button ng-click="removeSelForm(user)">delete</button>
</div>
</div>
</div>
</div>
<div class="buttonContainer text-center btn-container">
<br>
<button ng-disabled="userForm.$invalid" type="button" id="adduser" ng-click="adduser()">Add user</button>
<button type="button" class="btn button--default btn--small pull-center">Close</button>
</div>
</form>
</div>

Related

How to delay my ng-init function until my api call is success

I am working on dynamic form with ng-repeat. I am using oi-select for loading my location. I am loading this form inside modal popup. Regarding get my location values i am calling one api function on click of my modal open button. On success of this api call i was calling ng-init method. As per my requirement i should make this api call on click of modal open button. If i am clicking that button at first time, by default my first location value is not loaded inside select-box. Because my ng-init function called before my api call. Other than first time its working fine. Only first time it was not loaded that location[0] value defaultly . My question is how to delay this ng-init function?. Is there any other way to resolve this issue. Here i attached my plunker link .Please help me out from this issue. https://plnkr.co/edit/xDVetaZIzpFdKLS9ihU6?p=preview
html code
<body class="container row">
<div ng-app="myApp">
<div ng-controller="myCtrl">
<a class="btn btn-primary" data-toggle="modal" href='#modal-id' ng-click="getLocation()">Trigger modal</a>
<div class="modal fade" id="modal-id">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<form role="form" name='userForm' novalidate>
<div class="container">
<div class="row" ng-repeat="user in users">
<div class="form-group">
<div class="col-md-3">
<label>ID</label>
<input ng-model="user.id" id="user.id" name="user.id" placeholder="Enter bugid" type="text" required readonly disabled>
</div>
<div class="col-md-3">
<label>Comments</label>
<textarea ng-model="user.comment" id="textarea1" rows="1" required></textarea>
</div>
<div class="col-md-3 ">
<label>Location</label>
<oi-select ng-model="user.location" multiple oi-options="v for v in locations" ng-init='initLocation(user, locations)' name="select2" required>
</oi-select>
</div>
</div>
</div>
</div>
<div class="buttonContainer text-center btn-container">
<br>
<button ng-disabled="userForm.$invalid" type="button" id="adduser" ng-click="adduser()">Add user</button>
<button type="button" class="btn button--default btn--small pull-center">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" type="text/css" />
<script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
</div>
</div>
js code
var app = angular.module('myApp', ['ngResource', 'oi.select']);
app.factory('commonService', function($http, $q) {
return {
preFCSManualReleases: function() {
var deferred = $q.defer();
var url = "data.json";
$http.get(url, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
data: ''
}).then(function(data) {
deferred.resolve(data.data);
});
return deferred.promise;
}
}
});
app.controller('myCtrl', function($scope, commonService) {
$scope.getLocation = function() {
$scope.ids = [1, 2];
commonService.preFCSManualReleases().then(function(data) {
$scope.locations = data;
console.log('$scope.location[0]==============>', $scope.locations[0])
$scope.initLocation = (user, locations) => {
if (!user.location.length) {
user.location.push(locations[0]);
}
}
});
$scope.users = $scope.ids.map(function(id) {
return {
id: id,
comment: "",
location: []
};
});
}
$scope.adduser = function() {
var data = $scope.users.map(function(user) {
return {
"userid": user.id,
"manualcomment": user.comment,
"location": user.location
}
});
console.log("data", data)
}
});
You can put a condition on the oi-select parent:
<div class="col-md-3" ng-if="locationsLoaded">
<label>Location</label>
<oi-select ng-model="user.location" multiple oi-options="v for v in locations" ng-init='initLocation(user, locations)' name="select2" required>
</oi-select>
</div>
You can then control the $scope.locationsLoaded in your controller:
$scope.getLocation = function() {
$scope.locationsLoaded = false;
commonService.preFCSManualReleases().then(function(data) {
$scope.locations = data;
console.log('$scope.location[0]==============>', $scope.locations[0])
$scope.initLocation = (user, locations) => {
if (!user.location.length) {
user.location.push(locations[0]);
}
}
$scope.locationsLoaded = true; // we now have the required data
});
}
The ng-if will compile the element once locationsLoaded is true and when the ng-init is triggered, you are sure that there is data.

How to reset Bootstrap Form

Here im using Bootstrap validations with AngularJs when my form is submitted the columns is reset but its shows all validation..But my aim is its should not display validations
Bootstrap
<div class="modal" id="modal1">
<div class="modal-dialog">
<div class="modal-content">
<form name="f1" novalidate ng-submit="Save(Auth.emp)">
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group">
<div class="row">
<div class="col-sm-4">
Email
</div>
<div class="col-sm-8">
<input type="text" name="email" class="form-control" ng-model="Auth.Email" ng-class="Submitted?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.email.$dirty ||Submitted) && f1.email.$error.required">Email REq</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-4">
Password
</div>
<div class="col-sm-8">
<input type="text" name="psw" class="form-control" ng-model="Auth.Password" ng-class="Submitted?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.psw.$dirty ||Submitted) && f1.psw.$error.required">Password REq</span>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" value="{{LoginAction}}" />
</div>
</form>
</div>
</div>
</div>
AngularCode.Js
$scope.Save = function (emp) {
if ($scope.LoginAction = "Login") {
$scope.Submitted = true;
if ($scope.isFormValid == true) {
var ss = {
Email: $scope.Auth.Email,
Password: $scope.Auth.Password,
}
var xxer = myServices.GetLogin(ss);
xxer.then(function (msg) {
$scope.msg = msg.data;
$('#modal2').modal('show')
Reset();
})
}
}
}
Reset
function Reset() {
$scope.Email = '';
$scope.Password = '';
}
I think you looking for this:
function Reset() {
$scope.Auth.Email = ''
$scope.Auth.Password = '';
}
You can set a model at the same level as the form tag and make all other inputs sub properties. Then set form model at the root level to an empty object when you click on reset. Here's a codepen.
function exampleController($scope) {
$scope.reset = function() {
$scope.form = {};
};
}
angular
.module('app', [])
.controller('exampleController', exampleController);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div class="row" ng-app="app" ng-controller="exampleController">
<form novalidate ng-model="form">
<input ng-model="form.email" type="email" />
<input ng-model="form.password" type="password" />
</form>
<button ng-click="reset()">Reset</button>
<pre>{{form}}</pre>
</div>

Getting form values

angular.module('app', [])
.controller('mainCtrl', ['$scope', function ($scope) {
$scope.checkVal = function () {
console.log('entered');
console.log($scope.data.user)
}
$scope.data = {
//to keep the data from the api or any static data
//this will used to show the data in the view
user: {
fname: '',
lname: '',
email: '',
password: ''
}
};
$scope.methods = {
//this will called from the views to interact with properties and data
//use methods to change the values
checkVal: function () {
console.log('entered');
console.log($scope.data.user)
},
};
$scope.properties = {
//only to change views for ng-if and ng-show
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div action="#" ng-controller="mainCtrl as ctrl">
<div id="modal-login" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form action="#home" ng-submit="ctrl.methods.checkVal()">
<div class="modal-body">
<div class="form-group">
<input ng-model="ctrl.data.user.email" type="text" name="user-email" placeholder="Email:" required>
</div>
<div class="form-group">
<input ng-model="ctrl.data.user.password" type="password" name="password" placeholder="Password:" required>
</div>
</div>
<div class="modal-footer">
<div class="form-group clearfix">
<button type="submit" class="btn btn-primary">Login</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
I am trying to insert the values from the form in the object that i created in the controller. But somehow it isn't doing that. I don't understand why the data binding of this form doesn't give the output in the console like i asked it to. What am i doing wrong?
html
<body>
<div action="#" ng-controller="mainCtrl as ctrl">
<div id="modal-login" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form action="#home" ng-submit="ctrl.methods.checkVal()">
<div class="modal-body">
<div class="form-group">
<input ng-model="ctrl.data.user.email" type="text" name="user-email" placeholder="Email:" required>
</div>
<div class="form-group">
<input ng-model="ctrl.data.user.password" type="password" name="password" placeholder="Password:" required>
</div>
</div>
<div class="modal-footer">
<div class="form-group clearfix">
<button type="submit" class="btn btn-primary">Login</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
js
angular.module('app', [])
.controller('mainCtrl', ['$scope', function ($scope) {
$scope.checkVal = function () {
console.log('entered');
console.log($scope.data.user)
}
$scope.data = {
//to keep the data from the api or any static data
//this will used to show the data in the view
user: {
fname: '',
lname: '',
email: '',
password: ''
}
};
$scope.methods = {
//this will called from the views to interact with properties and data
//use methods to change the values
checkVal: function () {
console.log('entered');
console.log($scope.data.user)
},
};
$scope.properties = {
//only to change views for ng-if and ng-show
}
}])
becaues you use controllerAs in view you must use this format
angular.module('app', [])
.controller('mainCtrl', ['$scope', function ($scope) {
var vm = this;
vm.checkVal = function () {
console.log('entered');
console.log($scope.data.user)
}
vm.data = {
//to keep the data from the api or any static data
//this will used to show the data in the view
user: {
fname: '',
lname: '',
email: '',
password: ''
}
};
vm.methods = {
//this will called from the views to interact with properties and data
//use methods to change the values
checkVal: function () {
console.log('entered');
console.log($scope.data.user)
},
};
vm.properties = {
//only to change views for ng-if and ng-show
}
Try this.
JSFiddle
<script>
angular.module('app', [])
.controller('mainCtrl', ['$scope', function ($scope) {
$scope.checkVal = function () {
console.log('entered');
console.log($scope.data.user)
}
$scope.data = {
//to keep the data from the api or any static data
//this will used to show the data in the view
user: {
fname: '',
lname: '',
email: '',
password: ''
}
};
$scope.methods = {
//this will called from the views to interact with properties and data
//use methods to change the values
checkVal: function (ctrl) {
console.log('entered');
console.log(ctrl)
},
};
$scope.properties = {
//only to change views for ng-if and ng-show
}
}])
</script>
<body ng-app="app">
<div action="#" ng-controller="mainCtrl as ctrl">
<div id="modal-login" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form ng-submit="methods.checkVal(data)">
<div class="modal-body">
<div class="form-group">
<input ng-model="data.user.email" type="text" name="user-email" placeholder="Email:" required>
</div>
<div class="form-group">
<input ng-model="data.user.password" type="password" name="password" placeholder="Password:" required>
</div>
</div>
<div class="modal-footer">
<div class="form-group clearfix">
<button type="submit" class="btn btn-primary">Login</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>

Fields values generated using ng-repeat is not getting while submit

Template for form submission. This page will display the form template. Initially it shows the TItle,Full Name. On clicking the 'Add Tags' link new input fields is been generated for entering tags.
On submit, the field input(story.tag) is not been included on RequestPayload
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-controller="Note" >
<div ng-repeat="story in items ">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" id="tag" required/>
</div>
<a ng-click="add()">Add Tags</a>
</div>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
script :- app.js
angular.module("getbookmarks", ["ngResource"])
.factory('Story', function ($resource) {
var Story = $resource('/api/v1/stories/:storyId', {storyId: '#id'});
Story.prototype.isNew = function(){
return (typeof(this.id) === 'undefined');
}
return Story;
})
.controller("StoryCreateController", StoryCreateController);
function StoryCreateController($scope, Story) {
$scope.story = new Story();
$scope.save = function () {
$scope.story.$save(function (story, headers) {
toastr.success("Submitted New Story");
});
};
}
//add dynamic forms
var Note = function($scope){
$scope.items = [];
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
};
}
The story object inside ng-repeat is in another scope. This JSFiddle should do what you are looking for.
<div ng-app>
<div ng-controller="NoteCtrl">
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-repeat="story in items">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" required/>
</div> <a ng-click="add()">Add Tags</a>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
<div ng-repeat="test in items">
<label>Tag {{$index+1}}: {{test.tag}}</label>
</div>
</div>
</div>
The NoteController:
function NoteCtrl($scope) {
$scope.story = {};
$scope.items = [];
$scope.story.tag = $scope.items;
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
console.log($scope.story);
};
}

AngularJS select not updating after json push

I have the following controller:
function userControl($scope,$http) {
$scope.users = [
{"id":"0","name":"User1","roles":[{}]},
{"id":"1","name":"User2","roles":[{}]},
]
$scope.addUser = function() {
var nextid = $scope.getNextId();
$scope.users.push({id:nextid,name:$scope.userName});
$scope.userName = '';
//$apply();
};
$scope.getNextId = function() {
var count = 0;
angular.forEach($scope.users, function(data) {
count = data.id;
});
var count2 = parseInt(count)+1;
return count2;
};
}
And the following HTML:
<h2>Users</h2>
<div ng-controller="userControl">
<div ng-repeat="user in users">
{{user.id}} : {{user.name}}
</div>
<form ng-submit="addUser()">
<input type="text" ng-model="userName" placeholder="User Name" />
<input type="submit" value="add">
</form>
</div>
<h2>Add role to user</h2>
<div ng-controller="userControl">
<div ng-repeat="user in users">
<u>{{user.id}} : {{user.name}}</u><br />
<div ng-repeat="role in user.roles">
{{role.name}}
</div>
<br />
</div>
<form ng-submit="addRoleToUser()">
<select ng-model="selectedUser" name="userSelect" ng-options="user.id as user.name for user in users"></select>
<input type="submit" value="add">
</form>
</div>
When I add a user in the addUser() function I can see the user is added since it's listed under the ng-repeat, however the user name does not appear in the select box.
This is because you use the same controller twice. This creates two separate scopes. When you add a user in one scope it doesn't get added in the second scope. The fix is simple, join the code in one scope:
<div ng-controller="userControl">
<h2>Users</h2>
<div>
<div ng-repeat="user in users">
{{user.id}} : {{user.name}}
</div>
<form ng-submit="addUser()">
<input type="text" ng-model="userName" placeholder="User Name" />
<input type="submit" value="add">
</form>
</div>
<h2>Add role to user</h2>
<div>
<div ng-repeat="user in users">
<u>{{user.id}} : {{user.name}}</u><br />
<div ng-repeat="role in user.roles">
{{role.name}}
</div>
<br />
</div>
<form ng-submit="addRoleToUser()">
<select ng-model="selectedUser" name="userSelect" ng-options="user.id as user.name for user in users"></select>
<input type="submit" value="add">
</form>
</div>
</div>
An alternative approach is to create a Service since services are singletons:
module.factory('Users',function(){
var users = [
{"id":"0","name":"User1","roles":[{}]},
{"id":"1","name":"User2","roles":[{}]},
];
return {
users:users,
add:function(user){
users.push(user);
}
}
});
function userControl($scope, Users) {
$scope.users = Users.users;
$scope.addUser = function() {
var nextid = $scope.getNextId();
Users.add({id:nextid,name:$scope.userName});
$scope.userName = '';
};
$scope.getNextId = function() {
var count = 0;
angular.forEach($scope.users, function(data) {
count = data.id;
});
var count2 = parseInt(count)+1;
return count2;
};
}
This will work with your original markup.

Resources