<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Batch editable table</title>
<link rel='stylesheet prefetch' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>
<link rel='stylesheet prefetch' href='https://cdn.rawgit.com/esvit/ng-table/v0.8.1/dist/ng-table.min.css'>
<link rel='stylesheet prefetch' href='css/nqjzro.css'>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div ng-app="myApp" class="container-fluid">
<div class="row">
<div class="col-xs-12">
<h2 class="page-header">Batch editable table</h2>
<div class="row">
<div class="col-md-6">
<div class="bs-callout bs-callout-info">
<h4>Overview</h4>
<p>Example of how to create a batch editable table.</p>
</div>
</div>
<div class="col-md-6">
<div class="bs-callout bs-callout-warning">
<h4>Notice</h4>
<p>There are several directives in use that track dirty state and validity of the table rows. Whilst they are reasonally capable they are <em>not production tested - use at your own risk!</em> <a href="#" ng-click="isExplanationOpen = !isExplanationOpen">More details...</a></p>
<div ng-show="isExplanationOpen">
<p>If you look at the declarative markup for the <code>ngTable</code> you'll see a bunch of nested <code>ngForm</code> directives, with a common ancestor <code>ngForm</code> at the level of the table element. Each nested <code>ngForm</code> propogates their <code>$dirty</code> and <code>$invalid</code> state to this top level <code>ngForm</code>. This works great as you can enable/disable the buttons for saving the table based on the status of this single top-level <code>ngForm</code>.</p>
<p>This works up till the point that the user select's a new page to display in the table. At which point the existing nested <code>ngForm</code> directives are swapped out for new instances as the new data page is loaded. These new <code>ngForm</code> directives are always pristine and valid and this status propogates setting the corrosponding state on the top-level to be pristine and valid even though rows from the previous page are dirty and possibly invalid.</p>
<p>The solution is to have a set of directives that sit parallel to the <code>ngForm</code> directives that remember the state of the rows when the corrosponding <code>ngFrom</code> directives are destroyed and recreated. When <code>ngForm</code> directives are recreated they have their status reset by the directives that have remembered this state.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" ng-controller="demoController as demo">
<h3>ngTable directive</h3>
<div class="brn-group pull-right">
<button class="btn btn-default" ng-if="demo.isEditing" ng-click="demo.cancelChanges()">
<span class="glyphicon glyphicon-remove"></span>
</button>
<button class="btn btn-primary" ng-if="!demo.isEditing" ng-click="demo.isEditing = true">
<span class="glyphicon glyphicon-pencil"></span>
</button>
<button class="btn btn-primary" ng-if="demo.isEditing" ng-disabled="!demo.hasChanges() || demo.tableTracker.$invalid" ng-click="demo.saveChanges()">
<span class="glyphicon glyphicon-ok"></span>
</button>
<button class="btn btn-default" ng-click="demo.add()">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
<table ng-table="demo.tableParams" class="table table-bordered table-hover table-condensed editable-table" ng-form="demo.tableForm" disable-filter="demo.isAdding" demo-tracked-table="demo.tableTracker">
<colgroup>
<col width="70%" />
<col width="12%" />
<col width="13%" />
<col width="5%" />
</colgroup>
<tr ng-repeat="row in $data" ng-form="rowForm" demo-tracked-table-row="row">
<td title="'Name'" filter="{name: 'text'}" sortable="'name'" ng-switch="demo.isEditing" ng-class="name.$dirty ? 'bg-warning' : ''" ng-form="name" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{row.name}}</span>
<div class="controls" ng-class="name.$invalid && name.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="name" ng-model="row.name" class="editable-input form-control input-sm" required />
</div>
</td>
<td title="'Age'" filter="{age: 'number'}" sortable="'age'" ng-switch="demo.isEditing" ng-class="age.$dirty ? 'bg-warning' : ''" ng-form="age" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{row.age}}</span>
<div class="controls" ng-class="age.$invalid && age.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="number" name="age" ng-model="row.age" class="editable-input form-control input-sm" required/>
</div>
</td>
<td title="'Money'" filter="{money: 'number'}" sortable="'money'" ng-switch="demo.isEditing" ng-class="money.$dirty ? 'bg-warning' : ''" ng-form="money" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{row.money}}</span>
<div class="controls" ng-class="money.$invalid && money.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="number" name="money" ng-model="row.money" class="editable-input form-control input-sm" required/>
</div>
</td>
<td>
<button class="btn btn-danger btn-sm" ng-click="demo.del(row)" ng-disabled="!demo.isEditing"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
</table>
</div>
<div class="col-md-6" ng-controller="dynamicDemoController as demo">
<h3>ngTableDynamic directive</h3>
<div class="brn-group pull-right">
<button class="btn btn-default" ng-if="demo.isEditing" ng-click="demo.cancelChanges()">
<span class="glyphicon glyphicon-remove"></span>
</button>
<button class="btn btn-primary" ng-if="!demo.isEditing" ng-click="demo.isEditing = true">
<span class="glyphicon glyphicon-pencil"></span>
</button>
<button class="btn btn-primary" ng-if="demo.isEditing" ng-disabled="!demo.hasChanges() || demo.tableTracker.$invalid" ng-click="demo.saveChanges()">
<span class="glyphicon glyphicon-ok"></span>
</button>
<button class="btn btn-default" ng-click="demo.add()">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
<table ng-table-dynamic="demo.tableParams with demo.cols" class="table table-bordered table-condensed table-hover editable-table" ng-form="demo.tableForm" disable-filter="demo.isAdding" demo-tracked-table="demo.tableTracker">
<colgroup>
<col width="70%" />
<col width="12%" />
<col width="13%" />
<col width="5%" />
</colgroup>
<tr ng-repeat="row in $data" ng-form="rowForm" demo-tracked-table-row="row">
<td ng-repeat="col in $columns" ng-class="rowForm[col.field].$dirty ? 'bg-warning' : ''" ng-form="{{col.field}}" demo-tracked-table-cell>
<span ng-if="col.dataType !== 'command' && !demo.isEditing" class="editable-text">{{row[col.field]}}</span>
<div ng-if="col.dataType !== 'command' && demo.isEditing" class="controls" ng-class="rowForm[col.field].$invalid && rowForm[col.field].$dirty ? 'has-error' : ''" ng-switch="col.dataType">
<input ng-switch-default type="text" name="{{col.field}}" ng-model="row[col.field]" class="editable-input form-control input-sm" required />
<input ng-switch-when="number" type="number" name="{{col.field}}" ng-model="row[col.field]" class="editable-input form-control input-sm" required />
</div>
<button ng-if="col.dataType === 'command'" class="btn btn-danger btn-sm" ng-click="demo.del(row)" ng-disabled="!demo.isEditing"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
</table>
</div>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.min.js'></script>
<script src='https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.js'></script>
<script src="js/index.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular-route.js"></script>
</body>
</html>
以上是html代码
angular.module("myApp", ["ngTable", "ngTableDemos"]);
(function() {
"use strict";
angular.module("myApp").controller("demoController", demoController);
demoController.$inject = ["NgTableParams", "ngTableSimpleList"];
function demoController(NgTableParams, simpleList) {
var self = this;
var originalData = angular.copy(simpleList);
self.tableParams = new NgTableParams({}, {
dataset: angular.copy(simpleList)
});
self.deleteCount = 0;
self.add = add;
self.cancelChanges = cancelChanges;
self.del = del;
self.hasChanges = hasChanges;
self.saveChanges = saveChanges;
//////////
function add() {
self.isEditing = true;
self.isAdding = true;
self.tableParams.settings().dataset.unshift({
name: "",
age: null,
money: null
});
// we need to ensure the user sees the new row we've just added.
// it seems a poor but reliable choice to remove sorting and move them to the first page
// where we know that our new item was added to
self.tableParams.sorting({});
self.tableParams.page(1);
self.tableParams.reload();
}
function cancelChanges() {
resetTableStatus();
var currentPage = self.tableParams.page();
self.tableParams.settings({
dataset: angular.copy(originalData)
});
// keep the user on the current page when we can
if (!self.isAdding) {
self.tableParams.page(currentPage);
}
}
function del(row) {
_.remove(self.tableParams.settings().dataset, function(item) {
return row === item;
});
self.deleteCount++;
self.tableTracker.untrack(row);
self.tableParams.reload().then(function(data) {
if (data.length === 0 && self.tableParams.total() > 0) {
self.tableParams.page(self.tableParams.page() - 1);
self.tableParams.reload();
}
});
}
function hasChanges() {
return self.tableForm.$dirty || self.deleteCount > 0
}
function resetTableStatus() {
self.isEditing = false;
self.isAdding = false;
self.deleteCount = 0;
self.tableTracker.reset();
self.tableForm.$setPristine();
}
function saveChanges() {
resetTableStatus();
var currentPage = self.tableParams.page();
originalData = angular.copy(self.tableParams.settings().dataset);
}
}
})();
(function() {
"use strict";
angular.module("myApp").controller("dynamicDemoController", dynamicDemoController);
dynamicDemoController.$inject = ["NgTableParams", "ngTableSimpleList"];
function dynamicDemoController(NgTableParams, simpleList) {
var self = this;
var originalData = angular.copy(simpleList);
self.cols = [{
field: "name",
title: "Name",
filter: {
name: "text"
},
sortable: "name",
dataType: "text"
}, {
field: "age",
title: "Age",
filter: {
age: "number"
},
sortable: "age",
dataType: "number"
}, {
field: "money",
title: "Money",
filter: {
money: "number"
},
sortable: "money",
dataType: "number"
}, {
field: "action",
title: "",
dataType: "command"
}];
self.tableParams = new NgTableParams({}, {
dataset: angular.copy(simpleList)
});
self.deleteCount = 0;
self.add = add;
self.cancelChanges = cancelChanges;
self.del = del;
self.hasChanges = hasChanges;
self.saveChanges = saveChanges;
//////////
function add() {
self.isEditing = true;
self.isAdding = true;
self.tableParams.settings().dataset.unshift({
name: "",
age: null,
money: null
});
// we need to ensure the user sees the new row we've just added.
// it seems a poor but reliable choice to remove sorting and move them to the first page
// where we know that our new item was added to
self.tableParams.sorting({});
self.tableParams.page(1);
self.tableParams.reload();
}
function cancelChanges() {
resetTableStatus();
var currentPage = self.tableParams.page();
self.tableParams.settings({
dataset: angular.copy(originalData)
});
// keep the user on the current page when we can
if (!self.isAdding) {
self.tableParams.page(currentPage);
}
}
function del(row) {
_.remove(self.tableParams.settings().dataset, function(item) {
return row === item;
});
self.deleteCount++;
self.tableTracker.untrack(row);
self.tableParams.reload().then(function(data) {
if (data.length === 0 && self.tableParams.total() > 0) {
self.tableParams.page(self.tableParams.page() - 1);
self.tableParams.reload();
}
});
}
function hasChanges() {
return self.tableForm.$dirty || self.deleteCount > 0
}
function resetTableStatus() {
self.isEditing = false;
self.isAdding = false;
self.deleteCount = 0;
self.tableTracker.reset();
self.tableForm.$setPristine();
}
function saveChanges() {
resetTableStatus();
var currentPage = self.tableParams.page();
originalData = angular.copy(self.tableParams.settings().dataset);
}
}
})();
(function() {
"use strict";
angular.module("myApp").run(configureDefaults);
configureDefaults.$inject = ["ngTableDefaults"];
function configureDefaults(ngTableDefaults) {
ngTableDefaults.params.count = 5;
ngTableDefaults.settings.counts = [];
}
})();
/**********
The following directives are necessary in order to track dirty state and validity of the rows
in the table as the user pages within the grid
------------------------
*/
(function() {
angular.module("myApp").directive("demoTrackedTable", demoTrackedTable);
demoTrackedTable.$inject = [];
function demoTrackedTable() {
return {
restrict: "A",
priority: -1,
require: "ngForm",
controller: demoTrackedTableController
};
}
demoTrackedTableController.$inject = ["$scope", "$parse", "$attrs", "$element"];
function demoTrackedTableController($scope, $parse, $attrs, $element) {
var self = this;
var tableForm = $element.controller("form");
var dirtyCellsByRow = [];
var invalidCellsByRow = [];
init();
////////
function init() {
var setter = $parse($attrs.demoTrackedTable).assign;
setter($scope, self);
$scope.$on("$destroy", function() {
setter(null);
});
self.reset = reset;
self.isCellDirty = isCellDirty;
self.setCellDirty = setCellDirty;
self.setCellInvalid = setCellInvalid;
self.untrack = untrack;
}
function getCellsForRow(row, cellsByRow) {
return _.find(cellsByRow, function(entry) {
return entry.row === row;
})
}
function isCellDirty(row, cell) {
var rowCells = getCellsForRow(row, dirtyCellsByRow);
return rowCells && rowCells.cells.indexOf(cell) !== -1;
}
function reset() {
dirtyCellsByRow = [];
invalidCellsByRow = [];
setInvalid(false);
}
function setCellDirty(row, cell, isDirty) {
setCellStatus(row, cell, isDirty, dirtyCellsByRow);
}
function setCellInvalid(row, cell, isInvalid) {
setCellStatus(row, cell, isInvalid, invalidCellsByRow);
setInvalid(invalidCellsByRow.length > 0);
}
function setCellStatus(row, cell, value, cellsByRow) {
var rowCells = getCellsForRow(row, cellsByRow);
if (!rowCells && !value) {
return;
}
if (value) {
if (!rowCells) {
rowCells = {
row: row,
cells: []
};
cellsByRow.push(rowCells);
}
if (rowCells.cells.indexOf(cell) === -1) {
rowCells.cells.push(cell);
}
} else {
_.remove(rowCells.cells, function(item) {
return cell === item;
});
if (rowCells.cells.length === 0) {
_.remove(cellsByRow, function(item) {
return rowCells === item;
});
}
}
}
function setInvalid(isInvalid) {
self.$invalid = isInvalid;
self.$valid = !isInvalid;
}
function untrack(row) {
_.remove(invalidCellsByRow, function(item) {
return item.row === row;
});
_.remove(dirtyCellsByRow, function(item) {
return item.row === row;
});
setInvalid(invalidCellsByRow.length > 0);
}
}
})();
(function() {
angular.module("myApp").directive("demoTrackedTableRow", demoTrackedTableRow);
demoTrackedTableRow.$inject = [];
function demoTrackedTableRow() {
return {
restrict: "A",
priority: -1,
require: ["^demoTrackedTable", "ngForm"],
controller: demoTrackedTableRowController
};
}
demoTrackedTableRowController.$inject = ["$attrs", "$element", "$parse", "$scope"];
function demoTrackedTableRowController($attrs, $element, $parse, $scope) {
var self = this;
var row = $parse($attrs.demoTrackedTableRow)($scope);
var rowFormCtrl = $element.controller("form");
var trackedTableCtrl = $element.controller("demoTrackedTable");
self.isCellDirty = isCellDirty;
self.setCellDirty = setCellDirty;
self.setCellInvalid = setCellInvalid;
function isCellDirty(cell) {
return trackedTableCtrl.isCellDirty(row, cell);
}
function setCellDirty(cell, isDirty) {
trackedTableCtrl.setCellDirty(row, cell, isDirty)
}
function setCellInvalid(cell, isInvalid) {
trackedTableCtrl.setCellInvalid(row, cell, isInvalid)
}
}
})();
(function() {
angular.module("myApp").directive("demoTrackedTableCell", demoTrackedTableCell);
demoTrackedTableCell.$inject = [];
function demoTrackedTableCell() {
return {
restrict: "A",
priority: -1,
scope: true,
require: ["^demoTrackedTableRow", "ngForm"],
controller: demoTrackedTableCellController
};
}
demoTrackedTableCellController.$inject = ["$attrs", "$element", "$scope"];
function demoTrackedTableCellController($attrs, $element, $scope) {
var self = this;
var cellFormCtrl = $element.controller("form");
var cellName = cellFormCtrl.$name;
var trackedTableRowCtrl = $element.controller("demoTrackedTableRow");
if (trackedTableRowCtrl.isCellDirty(cellName)) {
cellFormCtrl.$setDirty();
} else {
cellFormCtrl.$setPristine();
}
// note: we don't have to force setting validaty as angular will run validations
// when we page back to a row that contains invalid data
$scope.$watch(function() {
return cellFormCtrl.$dirty;
}, function(newValue, oldValue) {
if (newValue === oldValue) return;
trackedTableRowCtrl.setCellDirty(cellName, newValue);
});
$scope.$watch(function() {
return cellFormCtrl.$invalid;
}, function(newValue, oldValue) {
if (newValue === oldValue) return;
trackedTableRowCtrl.setCellInvalid(cellName, newValue);
});
}
})();
这是javascript文件 上面的代码是angularjs。它显示表加载数据,添加行,删除,编辑。 请解决这个问题。我得到错误[$ injector:modulerr]。请帮我解决
答案 0 :(得分:0)
修改:他们为ngTableDemos
look here创建了不同的代码集
要运行您的示例,您需要先加载ngTableDemos
相关代码,然后再加载样本。
对于codepen,要了解他们用于运行任何示例的文件,请仔细检查 Pen设置JavaScript标签。
可能你没有加载"ngTableDemos"
模块,所以如果需要加载关联文件或删除它
angular.module("myApp", ["ngTable"]);