我正在使用jQuery开发一个类似todo的应用程序,但我想切换到Angular.
有一个用于添加新项目的输入字段,但只要在此输入中输入任何内容,键击 - 及其后面的那些 - 将有效地移动到现有项目组中的新项目.这意味着新项目输入文本框始终为空.更好地展示而不是解释:
http://jsfiddle.net/29Z3U/4/(删除了许多细节,但我所指的应用程序的方面已经过演示).
Song List
一些jQuery:
var template = Handlebars.compile($('#song_form_template').html()), counter = (function(){var i=0; return function(){return ++i};})(), cloneNewSong = function(){ var count = counter(), templateVals = {song_id: 'song_' + count}; $('ul#new_song').append(template(templateVals)); }, addSong = function(event){ //exclude certain keys here cloneNewSong(); container = $(event.target).closest('li.song'); container.appendTo('ul#sortable_songs'); $(event.target) .removeAttr('placeholder') .focus(); //what I just typed disappears without this! why? }; $('ul#new_song').on('keypress', 'input', addSong); cloneNewSong();
请注意,新项目输入文本框始终保持为空,并且焦点的行为应该如此,因此您可以继续键入而不会中断.
应用程序代码变得越来越长,我甚至还没有尝试显示从JSON派生的现有歌曲列表.当然在Angular中,ngRepeat使这很容易.但是,我对Angular版本的尝试不起作用:http://plnkr.co/edit/xsGRiHFzfsVE7qRxgY8d?p = preview
Song List
JS:
var myapp = angular.module('songListApp', []); myapp.controller('songListController', function($scope){ songs = [ {"song_name":"song 1","more_info":""}, {"song_name":"song 2","more_info":""}, {"song_name":"song 3","more_info":""} ]; $scope.songs = songs; $scope.newSong = function(new_song){ var song = {"song_name": new_song.title, "more_info":""}; songs.push(song); new_song.title = ''; }; });
在解决焦点管理问题之前,我注意到Angular模型的更新总是落后于一次击键.我假设这是因为keypress事件在角色插入DOM之前发生.
我意识到从keypress切换到keyup会改变一些事情,但最初的设计是基于按键的响应性.
我尝试了一个自定义指令来绑定到输入事件,但事情并没有像我希望的那样:http : //plnkr.co/edit/yjdbG6HcS3ApMo1T290r?p=preview
我注意到angularjs.org的第一个代码示例(没有控制器的基本绑定)似乎没有我遇到的问题 - 在释放密钥之前更新了示例模型.
虽然有一个公认的答案,但我提出了一种不同的方法,这种方法更简单,控制器污染更少.
首先,控制器.它很简单.
myapp.controller('songListController', function($scope, $timeout){ $scope.songs = [ {"song_name":"song 1","more_info":""}, {"song_name":"song 2","more_info":""}, {"song_name":"song 3","more_info":""} ]; });
第二,标记部分
<input ng-keypress="createAndFocusIn(songs)" create-and-focus-in="#songs input" placeholder="enter song" autofocus />
解释,
当按下某个键时,它会创建一首歌并将焦点放在歌曲列表中createAndFocusIn(songs)
.
create-and-focus-in
指令提供scope.createAndFocusIn()
,因此除非使用此指令,否则控制器不必具有此功能.它接受选择器,在这种情况下,创建新元素的位置,#songs input
最后但最重要的是指令部分:
myapp.directive('createAndFocusIn', function($timeout){ return function(scope, element, attrs){ scope.createAndFocusIn = function(collection) { collection.push({song_name: String.fromCharCode(event.keyCode)}); $timeout(function() { element[0].value = ''; var el = document.querySelectorAll(attrs.createAndFocusIn); el[el.length-1].focus(); }); }; }; });
在指令中,除了由属性指定之外,它没有做太多其他事情.
而已.
这是工作演示:http://plnkr.co/edit/mF15utNE9Kosw9FHwnB2?p=preview
----编辑---- @KnewB说它在FF中不起作用.这里有Chrome/FF工作版.
在FF中,
按下键时未设置window.event.我们需要传递参数
event.keyCode不存在,我们需要同时检查keyCode || 则charCode
value和focus使光标位于第一个位置,因此需要先设置焦点然后再添加值
http://plnkr.co/edit/u2RtHWyhis9koQfhQEdW?p=preview
myapp.directive('createAndFocusIn', function($timeout){ return function(scope, element, attrs){ scope.createAndFocusIn = function(ev, collection) { collection.push({}); $timeout(function() { element[0].value = ''; var el = document.querySelectorAll(attrs.createAndFocusIn); el[el.length-1].focus(); el[el.length-1].value = String.fromCharCode(ev.keyCode||ev.charCode); }); }; }; });
而$event
现在通过:
<input ng-keypress="createAndFocusIn($event, songs)" create-and-focus-in="#songs input" placeholder="enter song" autofocus />