是否可以在按键之后但在键盘之前更新模型?

 只属于天天的牛牛 发布于 2023-02-04 18:09

我正在使用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的第一个代码示例(没有控制器的基本绑定)似乎没有我遇到的问题 - 在释放密钥之前更新了示例模型.

    1 个回答
    • 虽然有一个公认的答案,但我提出了一种不同的方法,这种方法更简单,控制器污染更少.

      首先,控制器.它很简单.

      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 
      />
      

      2023-02-04 18:11 回答
    撰写答案
    今天,你开发时遇到什么问题呢?
    立即提问
    热门标签
    PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有