Creating select all checkbox in VueJS trough loop - loops

I've created some data that are displayed trough a loop as table.
That code seems fine, however in my methods I get an error 'page is not defined'.
Does anyone know how do I define it?
Table:
<tr v-for="page in pages" v-bind:key="page">
<td>
<input type="checkbox" v-model="pageIds" #click="select" :value="page.id">
</td>
<td>{{page.name}}</td>
<td>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<span v-bind="attrs" v-on="on"
><v-icon class="icon delete">mdi-delete</v-icon></span
>
</template>
<span>Delete Page</span>
</v-tooltip>
</td>
</tr>
Methods:
<script>
export default {
data: () => ({
pages: [
{"id":"/","name":"/"},
{"id":"/index","name":"/index"},
{"id":"/about-us","name":"/about-us"}
],
selected: [],
allSelected: false,
pageIds: []
}),
methods: {
selectAll: function() {
this.pageIds = [];
if (this.allSelected) {
for (page in this.pages) {
this.pageIds.push(this.pages[page].id.toString());
}
}
},
select: function() {
this.allSelected = false;
}
}
};
</script>

change this in your code. it will resolve your error
from
v-for="page in pages" v-bind:key="page"
to
v-for="(page, index) in pages"
v-bind:key="index"

Related

Why does the Ajax not updating the model correctly?

I am new to angularjs and is using code sample in book "pro-angularjs" to do some test run (it has an initial list of items, but then use Ajax to update list):
<!DOCTYPE html>
<html ng-app="todoApp">
<head>
<title>TO DO List</title>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script src="angular.js"></script>
<script>
var model = {
user: "Adam",
items: [{ action: "Buy Flowers", done: false },
{ action: "Get Shoes", done: false },
{ action: "Collect Tickets", done: true },
{ action: "Call Joe", done: false }],
};
var todoApp = angular.module("todoApp", []);
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data;
});
});
todoApp.filter("checkedItems", function () {
return function (items, showComplete) {
var resultArr = [];
angular.forEach(items, function (item) {
if (item.done == false || showComplete == true) {
resultArr.push(item);
}
});
return resultArr;
}
});
todoApp.controller("ToDoCtrl", function ($scope) {
$scope.todo = model;
$scope.incompleteCount = function () {
var count = 0;
angular.forEach($scope.todo.items, function (item) {
if (!item.done) { count++ }
});
return count;
}
$scope.warningLevel = function () {
return $scope.incompleteCount() < 3 ? "label-success" : "label-warning";
}
$scope.addNewItem = function (actionText) {
$scope.todo.items.push({ action: actionText, done: false });
}
});
</script>
</head>
<body ng-controller="ToDoCtrl">
<div class="page-header">
<h1>
{{todo.user}}'s To Do List
<span class="label label-default" ng-class="warningLevel()"
ng-hide="incompleteCount() == 0">
{{incompleteCount()}}
</span>
</h1>
</div>
<div class="panel">
<div class="input-group">
<input class="form-control" ng-model="actionText" />
<span class="input-group-btn">
<button class="btn btn-default"
ng-click="addNewItem(actionText)">Add</button>
</span>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Description</th>
<th>Done</th>
</tr>
</thead>
<tbody>
<tr ng-repeat=
"item in todo.items | checkedItems:showComplete | orderBy:'action'">
<td>{{item.action}}</td>
<td><input type="checkbox" ng-model="item.done" /></td>
</tr>
</tbody>
</table>
<div class="checkbox-inline">
<label><input type="checkbox" ng_model="showComplete"> Show Complete</label>
</div>
</div>
</body>
</html>
the only change i made was:
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data;
});
});
it was initially:
$http.get("todo.json").success(function (data) {
model.items = data;
});
which does not run with the latetest version angularjs, and so i made the change.
when debugging, i found that the initial value of model.items is:
and it is correctly showing in UI (see left side of screenshot).
After the ajax, its value is updated to 'data' whose value is:
the value of data looks fine to me (same as initial value of items).
But after i let go the debugger, finally in UI all items are gone.
I do understand why? it seems 'items' is the same as 'data'. Anyone has a clue on how i can debug further to find out the root cause?
Thanks,
btw, the 'todo.json' i used is below:
[{ "action": "Buy Flowers", "done": false },
{ "action": "Get Shoes", "done": false },
{ "action": "Collect Tickets", "done": true },
{ "action": "Call Joe", "done": false }]
You are not updating your model correctly. As you can see from your screenshot, data contains an object data which should be assigned to your model.
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data.data;
});
});

AngularJS mg-repeat items with checkbox preventing default on cancelled confirmation

I am using angular (first version) and I having trouble trying to accomplish a task. I have a list of item that I retrieve from the server DB. I am listing those items in a HTML table. There's a Boolean field that I want to update dynamically when the user check or uncheck a checkbox. The problem is during the confirmation. When I cancel the confirmation the check if still retaining its state (check/uncheck) and not going back to its previous state. I tried using "preventDefault", it didn't work. I tried "refreshing" the item array so the view might refresh the data, it didn't work. Here's a fiddle with a representation of what I have:
Fiddle
<div ng-app ng-controller="demoController">
<h3>
<span class="status">{{ status }}</span>
</h3>
<h2>
Movies i've seen
</h2>
<table>
<tr>
<th>Name</th>
<th>Have I seen it?</th>
</tr>
<tbody>
<tr ng-repeat="movie in movies">
<td> {{movie.name}}</td>
<td style="text-align: center">
<input value=" {{ movie.name }}" type="checkbox" ng-checked="movie.seen" ng-click="confirmSeen(this, $index)" /> </td>
</tr>
</tbody>
</table>
</div>
function demoController($scope) {
$scope.status = "AngularJS is up";
$scope.confirmSeen = function(e, idx) {
var movie = $scope.movies[idx];
if (movie !== undefined) {
var msg = "";
if(movie.seen) {
msg = "Are you sure you want to mark " + movie.name + " as unseen?";
} else {
msg = "Are you sure you want to mark " + movie.name + " as seen?";
}
if (confirm(msg)) {
movie.seen = !movie.seen;
$scope.movies.splice(idx, 1, movie);
} else {
$scope.movies.splice(idx, 1, movie);
e.stopImmediatePropagation();
e.preventDefault();
}
} else {
e.stopImmediatePropagation();
e.preventDefault();
}
}
$scope.movies = [{
name: "Conan",
seen: false
}, {
name: "Scarface",
seen: true
}, {
name: "GhostBuster",
seen: false
}, {
name: "The Shawshank Redemption",
seen: true
}, {
name: "Goodfellas",
seen: true
}, {
name: "Life",
seen: false
}];
}
You've got to pass the $event in the ng-click function.
Simply replace:
ng-click="confirmSeen(this, $index)"
To:
ng-click="confirmSeen($event, $index)"

What triggers a function call in other column when ngmodel changes in first column?

Consider the snippet:
JS
var mod = angular.module('module', []);
mod.controller('controller', function($scope) {
$scope.items = [{
id: 1,
label: 'aLabel',
subItem: {
name: 'aSubItem'
}
}, {
id: 2,
label: 'bLabel',
subItem: {
name: 'bSubItem'
}
}]
$scope.getValue = function(ngmodel) {
// some code goes here...
}
});
HTML
<body ng-controller='controller'>
<div>
<table>
<tr ng-repeat='count in counter'> // 5 times
<td>
<select ng-options="item.id as item.label for item in items"
ng-model="selected[$index]">
</select>
</td>
<td>
{{getValue(1)}}
</td>
<td>
</td>
</tr>
</table>
</div>
</body>
As soon as I select some value from the dropdown (select tag) in the first column, I notice that the function in the second column is triggered? What is the reason for this? What exactly is happening behind the scenes?
The reason is you are doing it inside ng-repeat
<tr ng-repeat = 'count in counter'>
You need to pass the object on the controller, in order to do some action on the same.
{{getValue(obj)}}

How to go from one <a> to another <a> in angularJs

CONTROLLER
$scope.employee = {};
$scope.setEmployee = function (employee) {
$scope.employeeId = employee.id;
$scope.employee = employee;
a($scope.employeeId);
};
var a = function () {
$scope.meetingTypes = MeetingService.findByEmployee({
'employeeId': $scope.employeeId
}, function () {
angular.forEach($scope.meetingTypes, function (meetingType) {
$scope.meetings = MeetingService.findByMeetingType(meetingType);
});
});
};
TEMPLATE
<tr>
<td>
<a ng-repeat="meetingType in meetingTypes">
- {{meetingType}}
</a>
<a ng-repeat="meeting in meetings">
- {{meeting}}
</a>
</td>
</tr>
Here I want to open second <a> tag on click of first <a> tag
The view should like tree view
LIKE :
- meeting_type
- meeting 1
- meeting 2
all services are declared in my .factory
Here I am getting meeting Type properly but i want to open list of meetings on click of meetingType <a> tag but i am not getting meetings here,
Is ng-href is helpfull here ?
Here is a some sample code which I think demonstrates what you want to acheive -
<table ng-app="myApp" ng-controller="TestCtrl">
<tr>
<td>Get Meetings</td>
</tr>
<tr>
<td>
<ul>
<li ng-repeat="meetingType in meetingTypes track by $index">
- {{meetingType.typeName}}
<ul ng-show="showMeetings && meetingType.meetings.length>0">
<li ng-repeat="meeting in meetingType.meetings track by $index">
<a>- {{meeting}}</a>
</li>
</ul>
</li>
</ul>
</td>
</tr>
</table>
javascripts -
'user strict';
angular.module('myApp', [])
.controller('TestCtrl', function($scope) {
$scope.employee = {};
$scope.meetingTypes = {};
$scope.setEmployee = function(employee) {
$scope.employeeId = 1;
//$scope.employee = {};
a($scope.employeeId);
};
var a = function() {
// your service should return this json
$scope.meetingTypes = [{
typeName: 'abc',
meetings: ['meeting1', 'meeting2', 'meeting3']
}, {
typeName: 'def',
meetings: ['meeting4', 'meeting5', 'meeting6']
}, {
typeName: 'ghi',
meetings: ['meeting7', 'meeting8', 'meeting8']
}];
};
});
jsfiddle

How to remove object from array within ng-repeat with AngularJS?

I am having an array with objects like [{...}, {...}] which I am outputting with ng-repeat. Then I have a delete button with a function to delete it.
Is there a simple way to delete it in AngularJS, perhaps with $index? Or I need to specify an ID on every object as an property?
If you don't apply a filter to reorder or filter your array, you can do this:
<div ng-repeat="item in items" ng-click="delete($index)">{{item}}</div>
And the delete function:
$scope.items = [...];
$scope.delete = function (index) {
$scope.items.splice(index, 1);
}
Another way to do it without filter problems: (ONLY IE9+)
<div ng-repeat="item in items | orderBy: 'id'" ng-click="delete(item)">{{item}}</div>
And the delete function:
$scope.items = [...];
$scope.delete = function (item) {
$scope.items.splice($scope.items.indexOf(item), 1);
}
http://jsfiddle.net/oymo9g2f/2/
Here is another example, using Jade too:
template.jade:
label All Items
ul.list-group
li.list-group-item(ng-repeat="item in items | orderBy: '_id'")
strong {{item.name}}
a.trash(ng-click='deleteItem(item)')
//a.trash is a bootstrap trash icon, but you don't need to use it.
controller.js:
$scope.deleteItem = function (item) {
$scope.items.splice($scope.items.indexOf(item),1);
}
removeWith
comparison for each element in a collection to the given properties object,
returning an array without all elements that have equivalent property values.
$scope.collection = [
{ id: 1, name: 'foo' },
{ id: 1, name: 'bar' },
{ id: 2, name: 'baz' }
]
<tr ng-repeat="obj in collection | removeWith:{ id: 1 }">
{{ obj.name }}
</tr>
<tr ng-repeat="obj in collection | removeWith:{ id: 1, name: 'foo' }">
{{ obj.name }}
</tr>
First try to do it this way, but the listing was not actualized at runtime.
$scope.delete = function (index) {
delete $scope.items[index];
}
Then with the answer given above by Facundo Pedrazzini did work properly for me.
$scope.delete = function (index) {
$scope.items.splice(index, 1);
}
Version: AngularJS v1.6.4
In blade.php
<table style="width:100%;">
<tr ng-repeat="name in planFormData.names track by $index">
<td>
<div class="form-group">
<label>Plan Name<span style="color:red;">*</span> </label>
<input type="text" class="form-control" ng-model="planFormData.names[$index].plan_name" name="plan_name" id="status-name" placeholder="Plan Name" autocomplete="off" required>
</div>
</td>
<td>
<i class="icon-plus" ng-click="addRow($index)" ng-show="$last"></i>
<i class="icon-trash" ng-click="deleteRow($event,name)" ng-show="$index != 0"></i>
</td>
</tr>
</table>
In controller.js
$scope.deleteRow = function($event, name) {
var index = $scope.planFormData.names.indexOf(name);
$scope.planFormData.names.splice(index, 1);
};
In Angular 6, I did similar for Multi Dimensional Array. It's working
RemoveThisTimeSlot(i: number, j: number) {
this.service.formData.ConsultationModelInfo.ConsultationWeekList[i].TimeBlockList.splice(j, 1);
}

Resources