delete dynamically added values to the ng-repeat(angularjs) - javascript

First of all, happy thanksgiving to everyone of you !!
I have this plunker-> http://plnkr.co/edit/N2bs5xqmtsj3MmZKEI25?p=info
User selects all the three values and only then the 'Add' button is enabled for addition.
Once clicked, the entries selected are shown below using ng-repeat. I also a delete button button to every row which gets added. How can i ensure that the delete functionality works in this case. ? i.e. if i click delete, only that particular row will be deleted.
Secondly, if u have noticed during the first add, a single delete button is shown above the first row. how can i remove that?
I also want to save the selected files in the controller so i can give those data to the backend. How can i know which options have been selected by user.
here is the plunker code-
HTML
<div ng-controller="Controller">
<form name="form" novalidate>
<input type='file' onchange="angular.element(this).scope().fileNameChanged(this)" ng-model="document" valid-file required>
<select name="singleSelect" ng-model="activeItem.content" ng-options="foo as foo for foo in contentarray" required>
<option ng-if="contentarray.length > 1" value="" selected>Choose</option>
</select>
<select name="singleSelect1" ng-model="activeItem.content1" ng-options="foo as foo for foo in content1array" required>
<option ng-if="content1array.length > 1" value="" selected>Choose</option>
</select>
<button ng-click="addItem()" ng-disabled="disableAdd || (form.$invalid && (!form.$valid && 'invalid' || 'valid'))">Add</button>
</form>
<div ng-repeat="item in items" ng-show="isvisible">
<a>{{item.name}}</a>
<a>{{item.content}}</a>
<a>{{item.content1}}</a>
<button ng-click="deleteItem()">Delete</button>
</div>
</div>
JS code
var app = angular.module('Select', []);
app.controller('Controller', function($scope, $timeout) {
/* for adding optional file based selection values selected by the user*/
$scope.isvisible = false; /* display 1st line when user clicks on add button*/
$scope.items = [{
}];
$scope.activeItem = {
name: '',
content: '',
content1: ''
}
$scope.fileNameChanged = function (el) {
$scope.activeItem.name = el.files[0].name
}
$scope.addItem = function () {
$scope.isvisible = true;
$scope.items.push($scope.activeItem);
if ($scope.items.length > 6) {
$scope.disableAdd = true
}
$scope.activeItem = {} /* reset active item*/
angular.element("input[type='file']").val(null); /* To clear the input type file selected for next selection*/
}
/* for showing select options and enabling add button only when both the options are selected*/
$scope.content = {};
$scope.content1 = {};
$scope.contentarray = ['2', '3'];
$scope.content1array = ['12', '121', '1233', '1211'];
$scope.trigger = function () {
$timeout(function () {
$('form.bad select').trigger('change');
})
}
});

I am referring to your deleteItem() and delete-button-problem:
You will have to implement your deleteItem() method in your controller. ng-repeat will automatically update your list, when you delete an item from the model ìtems, no need for angular.element. This works, because of two-way data-binding in Angular.
Add an id to your ìtems and use that to delete the item from the model e.g.:
$scope.addItem = function() {
//...
$scope.activeItem.id = $scope.items.length;
$scope.items.push($scope.activeItem);
//...
}
$scope.deleteItem = function(item) {
$scope.items.splice(item.id, 1);
}
In your ng-repeat you need to define your button like this:
<button ng-click="deleteItem(item)">Delete</button>
Your other problem is with the additional delete-button: That is displayed, because you initialize your model ìtems with an empty element. Initialize like this instead and the button will not be shown:
$scope.items = [];
Hope that helps

Related

replacing ng-show with ng-if

in my accordion(created directive called expander for this) i have question and yes/no drop down answers http://jsfiddle.net/xVZEX/116/
<expander ng-repeat="form in FormDataList.SectionList">
<div id="{{form.SectionID}}">
<div ng-repeat="question in form.QuestionList">
<span>{{question.QuestionText}}</span>
<select name="ans_{{form.SectionID}}_{{$index}}" ng-model="item"
ng-change="CalculateValidationPoints(item, question,
form.SectionID)" ng-options="ans as ans.AnswerText for
ans in question.AnswerList">
<option value="">--Select--</option>
</select>
<input type="text" ng-model="ExitName"
ng-show="name_{{question.QuestionID}}.show"
placeholder="Name"/>
<input type="text" ng-model="ExitTitle"
ng-show="name_{{question.QuestionID}}.show" placeholder="Title"/>
</div>
</div>
</expander>
I am displaying 20 questions. User can choose yes/no for answer for each question and move to next. The last question needs user to fill in their Name and Title if he/she choose yes. if for last question user chooses no then Name and Title is not needed.
To achieve this I have added two inputs ExitName and ExitTitle with NG-show in my expander and in my controller I show and hide my inputs for the question
if (question.QuestionText === "Was exit conference conducted?" && selectedAnswer.AnswerText === "Yes") {
var propName = "name_" + selectedAnswer.QuestionID;
var propTitle = "title_" + selectedAnswer.QuestionID;
$rootScope[propName] = {
show: true
};
$scope[propName] = $rootScope[propName];
$rootScope[propTitle] = {
show: true
};
$scope[propTitle] = $rootScope[propTitle];
$scope.IsExit = true;
}
else {
$scope.IsExit = false;
}
it works perfectly. But i am not happy with this as in the DOM there will be two input ExitName and ExitTitle for all 20 question only hidden. I want to replace ng-show with ng-if.
how can I change my code to make ng-if work.
Edit--------
So for testing i created an input
<input type="text" ng-if="name_{{question.QuestionID}}.show"/>
in my expander now as you suggested i chaged this inmy controller
if (question.QuestionText === "Was exit conference conducted?" && selectedAnswer.AnswerText === "Yes") {
var vm = this;
var propName = "name_" + selectedAnswer.QuestionID;
var propTitle = "title_" + selectedAnswer.QuestionID;
vm[propName] = {
show: true
};
}
else {
vm[propName] = {
show: false
};
}
does not work

Remove unchecked value from an array angular js

I am new to angular js. I have a checkbox with a table .
<td><input type="checkbox" ng-if="report.attributes.message.length > 0" ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">{{ report.attributes.message }}</td>
Here , I have a method getcheckedData(). So, In that method
var messages = [];
$scope.getcheckedData = function(SelectedVal) {
$("input:checkbox[type=checkbox]:checked").each(function() {
if ($.inArray(SelectedVal , messages) === -1){
messages.push(SelectedVal);
}
});
return messages;
};
I have an array which I declared globally,.So, I want to take the value of selected checkbox table data into that array. I am able to get that value in array. So, when user unchecks then the value which is unchecked should also get removed from that array . So, when user checks then ,
I have given one button on that I am sending all checked messages to the backend.
So, When I uncheck and press the button that time all messages still remain in the array.
$scope.sendAllMessages = function() {
uploadService.SendMessagesToQueue(uploadService.currentFileName,$scope.documentType,messages)
.then(function () {
}, function (error) {
$scope.errorMessage = error.status + " : " + error.statusText;
toastr.error($scope.errorMessage, 'Error : ' + error.status);
if (error.status === 401) {
loginService.authenticationError();
}
})
.finally(function () {
});
};
For button -
<button type="submit" ng-click = "sendAllMessages()" class="button-size btn btn-primary">Send </button>
so, How can I resolve this problem ?
What you have done is not the angular way of achieving what you need.
But if you need to do in the same way of Yours, here is the change you should do.
You should remove the value from the array if it is unchecked, using messages.splice(index, 1);
Here is the changed code of your's, without ng-model(not recommended)
var messages = [];
$scope.getcheckedData = function(SelectedVal) {
if ($.inArray(SelectedVal , messages) === -1){
messages.push(SelectedVal);
}
else
{
var index = messages.indexOf(SelectedVal)
messages.splice(index, 1);
}
return messages;
};
To achieve it in angular way, you need to use ng-model
Here is a sample using Angular
var app = angular.module('app', []);
function Ctrl($scope) {
$scope.messages = {
};
$scope.reports = [ { "name": "Sport", "id": "50d5ad" } , {"name": "General", "id": "678ffr" } ];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="Ctrl" ng-app="app">
<span ng-repeat="report in reports">
<label class="checkbox" for="{{report.id}}">
<input type="checkbox" ng-model="messages[report.id]" name="group" id="{{report.id}}" />
{{report.name}}
</label>
</span>
<pre ng-bind="messages | json"></pre>
</div>

Apply Expression if Checked Checkbox > 1

http://plnkr.co/edit/AxBJs2XICPtWaA7bup8G?p=preview
<li ng-repeat="d in data"><input type="checkbox"/>{{$index}}</li>
<button ng-show="checkismorethanone">Save</button>
I can't use ng-model because it will check all the checkbox. How can I know if there's any of the checkbox checked? I want to show the save button if anyone of the checkbox is checked, or hide the button if no more button is checked.
You can do something like this :
<li ng-repeat="d in data"><input type="checkbox" ng-model="d.val"/>{{$index}}</li>
<button ng-show="anyCheckBoxSelected()">Save</button>
And this in the controller file :
$scope.data = [{val:false, num:1 },{num:2, val: false},{num:3, val:false},{num:4, val:false}];
$scope.anyCheckBoxSelected = function() {
var checked = $filter("filter")($scope.data , {val:true} );
return checked.length;
}
Here is the plnkr, forked from your link :
http://plnkr.co/edit/VApxbuEBUljkJDjSusxw
Check demo: Plunker
You need an object, say results', to store themodelvalues of your selection. Useng-modelto bind the$index-thcheckbox toresults[$index]`.
<li ng-repeat="d in data"><input ng-model="results[$index]" value="{{d}}" type="checkbox"/>{{$index}}</li>
<button ng-show="checkismorethanone">Save</button>
{{ results | json }}
<button ng-show="showButton()">Submit</button>
In controller, The for loop iterates current selections to check whether some checkbox is checked. ng-show is true if any of the checkboxes is checked.
$scope.results = {};
$scope.showButton = function () {
for (var key in $scope.results) {
if ($scope.results[key]) {
return true;
}
}
};
Toggle the status of the submit button depending on the value of results.
You can just use a single variable to count the click,
If a checkbox is checked the increment the counter, if checkbox is not checked decrement the counter.
Show the button if counter count is greater then 0.
//index.html
<ul >
<li ng-repeat="d in data" >
<input type="checkbox" name="{{$index}}" ng-click="checkboxOnClick($event)" /> {{$index}}
</li>
</ul>
<button ng-show="checkCount">Save</button>
//app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.data = [1,2,3,4];
$scope.checkCount = 0;
$scope.checkboxOnClick = function($event){
if( $event.target.checked){
$scope.checkCount++;
}else{
$scope.checkCount--;
}
};
});
Check the plnkr,
http://plnkr.co/edit/KolYTZjzPvlyUGNF6elZ?p=preview

KnockoutJS, Checkbox list reflecting which groups my currently selected object belongs to?

This is the first time I post a question here, please let me know if I need to improve it. (including the title)
I have in my model two types of objects, Device and Group. A Device can belong to a Group or not, and a Group can contain Devices or not.
What I would like to do is to have a selectlist on the left, showing a list of Device.Name. When the user selects one of them, the details of the selected Device shows in the middle of the screen, and then on the right-hand side, have a list of checkboxes, each checkbox representing a Group.
The problem is I cannot find a way to define the Checked bindings of my checkboxes. I have tried defining an observableArray of CheckedGroup{ Group, bool }, but could not get the bool value to update dynamically according to the currently selected device.
My viewmodel:
function Device(data) {
this.DeviceId = ko.observable(data.DeviceId);
this.Name = ko.observable(data.Name);
this.Number = ko.observable(data.Number);
this.IpAddress = ko.observable(data.IpAddress);
this.Description = ko.observable(data.Description);
this.Groups = ko.observableArray();
this.Groups = $.map(data.Groups, function (grp, i) {
return grp;
});
}
function Group(data) {
var self = this;
self.GroupId = ko.observable(data.GroupId);
self.Name = ko.observable(data.Name);
self.Description = ko.observable(data.Description);
}
function DevicesViewModel() {
// Data
var self = this;
self.devices = ko.observableArray([]);
self.groups = ko.observableArray([]);
self.currentdevice = ko.observable();
$.getJSON(deviceapiuri, function (data) {
var mappeddevices = $.map(data, function (dev, i) {
return new Device(dev)
});
self.devices(mappeddevices);
});
$.getJSON(groupapiuri, function (data) {
var mappedgroups = $.map(data, function (grp, i) {
return new Group(grp)
});
self.groups(mappedgroups);
});
}
My View :
// The device list on the left side
<select id="devicelist_input" size="2" data-bind="options: devices, optionsText: function (i) { return i.Name }, value: currentdevice"> </select>
//One of the input fields that are bound to my currentdevice - this correctly updates when selecting my device.
<input id="stbdescription_input" type="text" data-bind="value: currentdevice() && currentdevice().Description" />
//The list of checkboxes I an trying to bind - the list is populated correctly, but the boxes' Checked property won't update according to the currentdevice
<div id= "group_check_list_input" data-bind="foreach: groups">
<input type="checkbox" class="groupcheckbox" data-bind="value: $data, Checked:$root.currentdevice() && $root.currentdevice().Groups" />
It's quite difficult to get the checkbox selecting. The key thing to doing this is you must be using the same object in both the DevicesViewModel.groups and Device.groups. It needs to be exactly the same object and not just an object with the same data.
You can do this by passing in the viewModel groups to the device constructor and then if the the groupId matches then you add the group to the device groups. I did this using the following code:
function Device (device, groups) {
this.DeviceId = ko.observable(device.DeviceId);
this.Name = ko.observable(device.Name);
this.Number = ko.observable(device.Number);
this.IpAddress = ko.observable(device.IpAddress);
this.Description = ko.observable(device.Description);
var mappedGroups = $.map(device.Groups, function (grp) {
var group = ko.utils.arrayFilter(groups, function(group)
{
return group.GroupId() == grp.GroupId;
});
return group[0];
});
this.Groups = ko.observableArray(mappedGroups);
};
Other problems with your code is you are using value binding for the checkbox when you need to use checkedValue and checked can be just be set to $parent.Groups if you are using a with for the currentdevice.
<select data-bind="options: devices, optionsText: 'Name', value: currentdevice, optionsCaption: 'Select a device'"></select>
<div data-bind="with: currentdevice">
<label>DeviceId:</label>
<span data-bind="text: DeviceId"></span>
<label>Name:</label>
<span data-bind="text: Name"></span>
<label>Number:</label>
<span data-bind="text: Number"></span>
<label>IpAddress:</label>
<span data-bind="text: IpAddress"></span>
<label>Description:</label>
<span data-bind="text: Description"></span>
<div data-bind="foreach: $root.groups">
<input type="checkbox" data-bind="checked: $parent.Groups, checkedValue: $data"/><span data-bind="text: Name"></span>
</div>
</div>
Here is the jsfiddle of it working:
http://jsfiddle.net/k4kAU/1/

Hide a Current Button on ng-click

I have a button for updating data in ng-form. This button only appear when some form input is changed. I done this with $dirty.
When the Update is clicked, I update the data. But I want to hide this button when it clicked.
I have an ng-click method on button click.
I tried to hide it like this :-
$(this).hide();
The above solutions doesn't work & i also want some solution which is not jquery based.
HTML
<button class="btn-small" ng-click="updateData('contactinformation')" ng-show="contactinformationform.$dirty">Update</button>
CODE
$scope.updateData = function (category) {
switch (category) {
case 'basicinformation':
$scope.categorynewdata = $scope.data.basicinformation[0];
break;
case 'contactinformation':
$scope.categorynewdata = $scope.data.contactinformation[0]
break;
}
var query = {
category: category
};
Patients.updateData().save(query).$promise.then(function (data) {
alert('Data updated successfully..!');
});
}
You can use ng-hide in your button like this
Define scope variable (Like flag) so that you can decide when to hide/show button.
<button ng-click="btnClicked()" ng-hide="hideMe">Submit</button>
Controller
// Initialize hideMe variable
$scope.hideMe = false;
$scope.btnClicked = function() {
/* your code */
$scope.hideMe = true;
}
You can Try like this
Working Demo
html
<div ng-app='myApp' ng-controller="ArrayController">
<form>
<input type="text" ng-model="name" ng-change='flag=false' />: Name
<br>
<input type="text" ng-model="age" ng-change='flag=false' />: Age
<br>
<button class="btn-small" ng-click="updateData('contactinformation')" ng-hide='flag'>Update</button>
</form>
</div>
script
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.name = 'Manu';
$scope.age = '21';
$scope.flag = true;
$scope.updateData = function (value) {
$scope.flag = true;
}
});

Categories

Resources