【问题标题】:How to focus a DOM child element from a Meteor event handler如何从 Meteor 事件处理程序中聚焦 DOM 子元素
【发布时间】:2016-04-14 18:23:58
【问题描述】:

我有一个事件处理程序,它设置一个会话变量来更改 DOM 元素中的内容——在本例中是一个表格单元格。

'dblclick td.itemName': function (evt) {
  Session.set("editItemName",true);
  evt.currentTarget.children[0].focus();
},


                <td class="itemName">
                {{#unless editItemName}}
                    {{name}} 
                {{else}}
                    <input class="editItemName" type="text" value="{{name}}" style="width:100px;">
                {{/unless}}
                </td>

很简单...

但是 evt.currentTarget.children 不起作用。一旦输入取代了文本,我想让它自动聚焦......流星文档说这是一个 DOM 对象,所以很奇怪,子函数不起作用......

谢谢

切特

【问题讨论】:

    标签: dom meteor


    【解决方案1】:

    当您双击并运行您的函数时,您将会话 editItemName 设置为 true,然后您尝试为输入元素提供焦点,但尚未重新渲染模板,因此input-element 尚未创建(模板将在您的函数返回后的某个时间重新呈现)。换句话说:evt.currentTarget.children[0] 不是对输入元素的引用。

    可能的解决方案 1

    在 HTML 5 中有一个名为 autofocus 的属性,您可以使用它(至少我可以在 Chrome 中使用)。只需将其添加到输入元素:

    <input autofocus="autofocus" class="editItemName" type="text" value="{{name}}" style="width:100px;">
    

    可能的解决方案 2

    否则,当模板被渲染并且您的输入元素存在于其中时,您必须使用 JavaScript 来关注它:

    Template.yourTemplate.rendered = function(){
    
        var input = this.find('.editItemName')
    
        if(input){
            input.focus()
        }
    
    }
    

    【讨论】:

    • 啊。有趣...不过,这是有道理的。任何想法如何解决这个问题?
    • @Chet 查看我改进后的答案。
    • 我想我将使用 x-editable... 显然我可以将它与陨石一起使用。没有把握。还在学习中...
    【解决方案2】:

    您正在尝试将焦点设置到尚未呈现的 DOM 元素。

    这个问题困扰了我一段时间。我曾尝试使用autofocus='autofocus' HTML 属性:它在 Firefox 中无效,而在 Chrome 中,它似乎只在第一次渲染元素时起作用。

    所以我们需要一个在模板渲染后调用的处理程序,以便使用 javascript 设置焦点。 Template.templateName.rendered 看起来像要走的路,但有一个问题:

    什么对我不起作用:

    <template name="itemName">
        <td class="itemName">
        {{#unless editItemName}}
            {{name}} 
        {{else}}
            <input type="text" value="{{name}}">
        {{/unless}}
        </td>
    </template>
    
    Template.itemName.rendered = function()
    {
        this.$('input').focus() 
    }
    

    执行此操作时,Template.yourTemplate.rendered 似乎仅在您第一次单击该项目时触发(您仅正确获得一次焦点)。

    什么对我有用:

    <template name="itemName">
        <td class="itemName">
        {{#unless editItemName}}
            {{name}} 
        {{else}}
            {{> itemNameEdit}}
        {{/unless}}
        </td>
    </template>
    
    <template name="itemNameEdit">
        <input type="text" value="{{name}}">
    </template>
    
    Template.itemNameEdit.rendered = function()
    {
        this.$('input').focus() 
    }
    

    流星专家有什么解释吗?

    【讨论】:

    • 在最近的流星版本中,他们更改了 template.rendered() 的一些功能。每当重新渲染该模板中的信息时,都会调用 Rendered。现在他们正在使用 Blade 模板系统,只有需要重新渲染的模板部分会被重新渲染,并且 Template.rendered 只会被调用一次:github.com/meteor/meteor/wiki/…
    • 非常感谢!我现在明白为什么拆分为 2 个模板有效:每次用户编辑项目名称时,第二个模板 itemNameEdit 会从 DOM 中添加和删除,并在需要时触发 Template.itemNameEdit.renderedTemplate.itemName.rendered 不是这种情况,它只被调用一次,因为itemNameEdit 留在 DOM 中。
    【解决方案3】:

    作为@Chet pointed out,Template.[name].rendered 不再在模板更新时触发,而是仅在模板首先渲染时触发,only once

    可以将回调传递给Tracker.afterFlush,每次更新模板时都会触发该回调。 即all reactive updates are processed

    Template.myTemplate.events({
      'dblclick td.itemName': function(e, t) {
        Session.set("editItemName",true);
    
        Tracker.afterFlush(function() {
          this.find('input').focus();
        }.bind(t));
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2015-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多