就地编辑内容编辑
Posted
技术标签:
【中文标题】就地编辑内容编辑【英文标题】:Edit In Place Content Editing 【发布时间】:2013-03-05 09:33:23 【问题描述】:使用ng-repeat
时,编辑内容的最佳方式是什么?
在我的理想情况下,添加的生日将是一个超链接,当点击它时,它将显示一个编辑表单 - 与当前的添加表单相同,带有一个更新按钮。
Live Preview (Plunker)
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.0/css/bootstrap-combined.min.css"
rel="stylesheet">
</head>
<body ng-app="birthdayToDo" ng-controller="main">
<div id="wrap">
<!-- Begin page content -->
<div class="container">
<div class="page-header">
<h1>Birthday Reminders</h1>
</div>
<ul ng-repeat="bday in bdays">
<li>bday.name | bday.date</li>
</ul>
<form ng-show="visible" ng-submit="newBirthday()">
<label>Name:</label>
<input type="text" ng-model="bdayname" placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" ng-model="bdaydate" placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</div>
<div id="push"></div>
</div>
<div id="footer">
<div class="container">
<a class="btn" ng-click="visible = true"><i class="icon-plus"></i>Add</a>
</div>
</div>
</body>
App.js:
var app = angular.module('birthdayToDo', []);
app.controller('main', function($scope)
// Start as not visible but when button is tapped it will show as true
$scope.visible = false;
// Create the array to hold the list of Birthdays
$scope.bdays = [];
// Create the function to push the data into the "bdays" array
$scope.newBirthday = function()
$scope.bdays.push(name:$scope.bdayname, date:$scope.bdaydate);
$scope.bdayname = '';
$scope.bdaydate = '';
;
);
【问题讨论】:
你的问题是指实际实现还是接口设计? @Flek 本来是为了实现界面设计简单 我来到这里是为了寻找你想做的事情,但你有没有注意到你在重复 'ul' 元素而不是 'li'?结果是您拥有与元素一样多的ul
,这是不正确的。
【参考方案1】:
您应该将表单放在每个节点内,并使用ng-show
和ng-hide
分别启用和禁用编辑。像这样的:
<li>
<span ng-hide="editing" ng-click="editing = true">bday.name | bday.date</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="bday.name" placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" ng-model="bday.date" placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</li>
这里的重点是:
我已将控件ng-model
更改为本地范围
已将 ng-show
添加到 form
,以便我们在编辑时显示它
添加了 span
和 ng-hide
以在编辑时隐藏内容
添加了一个ng-click
,它可以在任何其他元素中,将editing
切换到true
将ng-submit
更改为将editing
切换为false
这是你的updated Plunker。
【讨论】:
感谢您的出色回答 :) 我有一个问题,当我编辑它时似乎也显示了添加表单 - 因为它设置为 true 如果我的问题没有错,只需将$scope.visible = false
设置为newBirthday()
。这将使添加表单在您添加项目时消失。
为了限制处理,我会把它放在一个指令中,所以除非需要,否则不会发生 DOM 操作和编译。
我的意思是大多数条目不需要编辑,但我们正在对所有条目添加处理以添加功能。 ngShow
和 ngHide
不会停止功能 - 他们只是将 display: none
添加到 CSS 中。所以所有的绑定仍然是有线的,并且 DOM 仍然被操纵。如果我们将其作为指令执行,我们可以按需调用表单创建。这是我不久前创建的一个简单的就地编辑指令来说明:jsfiddle.net/joshdmiller/NDFHg。还有一个更复杂的:plnkr.co/edit/LVUIQD.
自 unstable Angular 1.1.5 以来,Angular 现在支持 ngIf 开箱即用。就像强调 1.1.5 是一个不稳定的版本一样。【参考方案2】:
我一直在寻找一个内联编辑解决方案,我发现了一个看起来很有前途的 plunker,但它对我来说开箱即用并不适用。在对代码进行了一些修改后,我让它工作了。感谢最初努力编写这篇文章的人。
该示例可在此处获得http://plnkr.co/edit/EsW7mV?p=preview
代码如下:
app.controller('MainCtrl', function($scope)
$scope.updateTodo = function(indx)
console.log(indx);
;
$scope.cancelEdit = function(value)
console.log('Canceled editing', value);
;
$scope.todos = [
id:123, title: 'Lord of the things',
id:321, title: 'Hoovering heights',
id:231, title: 'Watership brown'
];
);
// On esc event
app.directive('onEsc', function()
return function(scope, elm, attr)
elm.bind('keydown', function(e)
if (e.keyCode === 27)
scope.$apply(attr.onEsc);
);
;
);
// On enter event
app.directive('onEnter', function()
return function(scope, elm, attr)
elm.bind('keypress', function(e)
if (e.keyCode === 13)
scope.$apply(attr.onEnter);
);
;
);
// Inline edit directive
app.directive('inlineEdit', function($timeout)
return
scope:
model: '=inlineEdit',
handleSave: '&onSave',
handleCancel: '&onCancel'
,
link: function(scope, elm, attr)
var previousValue;
scope.edit = function()
scope.editMode = true;
previousValue = scope.model;
$timeout(function()
elm.find('input')[0].focus();
, 0, false);
;
scope.save = function()
scope.editMode = false;
scope.handleSave(value: scope.model);
;
scope.cancel = function()
scope.editMode = false;
scope.model = previousValue;
scope.handleCancel(value: scope.model);
;
,
templateUrl: 'inline-edit.html'
;
);
指令模板:
<div>
<input type="text" on-enter="save()" on-esc="cancel()" ng-model="model" ng-show="editMode">
<button ng-click="cancel()" ng-show="editMode">cancel</button>
<button ng-click="save()" ng-show="editMode">save</button>
<span ng-mouseenter="showEdit = true" ng-mouseleave="showEdit = false">
<span ng-hide="editMode" ng-click="edit()">model</span>
<a ng-show="showEdit" ng-click="edit()">edit</a>
</span>
</div>
使用它只需加水:
<div ng-repeat="todo in todos"
inline-edit="todo.title"
on-save="updateTodo($index)"
on-cancel="cancelEdit(todo.title)"></div>
更新:
另一种选择是为AngularJS使用现成的Xeditable:
http://vitalets.github.io/angular-xeditable/
【讨论】:
【参考方案3】:由于这是一个常见的功能,因此最好为此编写指令。事实上,有人已经这样做并开源了它。我在one of my projects 中使用了editablespan 库,效果很好,强烈推荐。
【讨论】:
【参考方案4】:我已经修改了你的 plunker,让它通过 angular-xeditable 工作:
http://plnkr.co/edit/xUDrOS?p=preview
这是内联编辑的常见解决方案 - 您可以使用 editable-text
指令创建超链接
切换到<input type="text">
标签:
<a href="#" editable-text="bday.name" ng-click="myform.$show()" e-placeholder="Name">
bday.name || 'empty'
</a>
对于日期,我使用editable-date
指令切换到html5 <input type="date">
。
【讨论】:
以上是关于就地编辑内容编辑的主要内容,如果未能解决你的问题,请参考以下文章
添加 div javascript,然后就地编辑 jquery
基于 QSqlTableModel 就地编辑新记录的 QTableView 不会在 PyQt 中保存编辑