【问题标题】:How to automatically focus first backbone-forms input field?如何自动聚焦第一个主干表单输入字段?
【发布时间】:2013-12-08 19:26:28
【问题描述】:

以下屏幕截图显示了登录和注册的组合表单:

以下模块用于渲染AuthView

MyApp.module("User", function(User, App, Backbone, Marionette, $, _) {

  User.AuthView = Marionette.ItemView.extend({

    className: "reveal-modal",
    template: "user/auth",

    ui: {
      signInForm: "#signin-form",
      signUpForm: "#signup-form"
    },

    events: {
      "focus input": "onFocus"
    },

    onFocus: function() {
      console.log("Some input field has received focus.");
    },

    onRender: function() {  
      this.signInForm = new Backbone.Form({
        schema: {
          signInEmail: { 
            type: "Text", 
            title: "E-Mail address"
          },
          signInPassword: { 
            type: "Password", 
            title: "Password"
          }
        }
      }).render();
      this.ui.signInForm.prepend(this.signInForm.el);

      this.signUpForm = new Backbone.Form({
        schema: {
          signUpEmail: { 
            type: "Text", 
            title: "E-Mail address"
          },
          signUpPassword: { 
            type: "Password", 
            title: "Password"
          },
          signUpPasswordConfirmation: { 
            type: "Password", 
            title: "Password confirmation"
          }
        }
      }).render();
      this.ui.signUpForm.prepend(this.signUpForm.el);
    }

  });
});

如何在每个子表单呈现时自动聚焦第一个字段?对于signInForm,第一个字段是signInEmail,对于signUpForm,第一个字段是signUpEmail
我试着听focus input 事件。当我点击其中一个输入字段时会触发此类事件,而不是之前。


同时,受当前答案的启发,我想出了以下辅助函数:

focusFirstFormField: function(form) {
  if (_.isUndefined(form)) {
    throw "IllegalStateException: Form is undefined."
  }
  // TODO: AuthView does not focus first sign-in field.
  var firstInput = form.find(':input:first');
  if (_.isObject(firstInput)) {
    if (firstInput.length > 0) {
      firstInput = firstInput[0];
    }
    else {
      throw "IllegalStateException: Form find returns an empty jQuery object."
    }
  }
  _.defer(function() {
    firstInput.focus();
  });
 }

尽管如此,仍然需要改进。

【问题讨论】:

    标签: backbone.js focus marionette backbone-views backbone-forms


    【解决方案1】:

    events 对象是 DOM 事件,通常由用户触发,因此在这种情况下您可能不想使用它。

    如果我对您的理解正确,您希望将焦点放在每个表单的第一个输入中,但由于您一次只能关注一件事并且它们一起呈现,您必须选择一个或另一个。

    最简单的选择是在 onRender 的末尾添加另一行,重点关注输入。如果您的输入正在生成类似这样的输入:

    <input type="text" name="signInEmail">
    

    然后你可以添加:

    this.$('[name=signInEmail]').focus();
    

    如果不是,您将不得不更改选择器 this.$(xxxx).focus() 以适应。

    【讨论】:

    • 我更喜欢 Billy Chanuser2503775 发布的更通用的选择方法,但仍然 +1 为我指明了正确的方向.
    【解决方案2】:

    您可以使用视图的onDomRefresh 事件。它会在视图渲染和 Dom 刷新后触发。

    onDomRefresh: function() {
      this.focusFirstInput();
    };
    
    focusFirstInput: function() {
      this.$(':input:visible:enabled:first').focus();
    };
    

    此解决方案适用于一般情况。但是,如果您使用的是 Bootstrap,请注意。我不能在那里完成这项工作。相反,我在字段中设置了autofocus: 'autofocus',它可以工作。

    【讨论】:

    • 谢谢!我测试了这两种实现。 评论第 1 部分:editorAttrs 每个单独的表单 schema 中设置 autofocus: 'autofocus' 可以正常加载,但不能刷新页面。此外,它不适用于更复杂的多页表单,在这些表单中我来回导航显示和隐藏各个子表单。
    • 评论第 2 部分onDomRefresh 对于设置页面重新加载的初始焦点非常有帮助。不过,我想提一下,我需要通过_.defer().focus() 调用来实现这一点。关于选择,我注意到 :input:visible:enabled:first 在页面重新加载时对我不起作用。使用:input:first 效果更好,尽管我在使用更复杂的表单时遇到了一些问题,它不选择第一个输入表单而是另一个。
    • @JJD,感谢您的评论。使用defer() 是明智且有用的:) 对于字段选择器,忽略:visible 可能适用于您的情况。但是如果表单是Rails风格的,首先需要注意隐藏csrf字段。
    【解决方案3】:

    您可以将其添加到onRender 方法中。

    this.ui.signInForm.find('input[type=text]:first').focus();
    this.ui.signUpForm.find('input[type=text]:first').focus();
    

    【讨论】:

    • 它适用于表单,但不适用于更复杂的表单,我可以在子表单之间来回导航。该方法仍然 +1,但我将采用更通用的方法。
    【解决方案4】:

    关于我使用的onRender 方法:

    $(this.el).find(':input[autofocus]').focus();
    

    然后我将autofocus="" 标志添加到我的HTML 节点上。这适用于刷新。

    【讨论】:

      猜你喜欢
      • 2016-01-02
      • 1970-01-01
      • 2022-08-16
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 2018-08-17
      • 1970-01-01
      • 2021-09-08
      相关资源
      最近更新 更多