【问题标题】:EmberJS 2.7 - how to bind attribute 'disabled' for a buttonEmberJS 2.7 - 如何为按钮绑定属性“禁用”
【发布时间】:2017-01-16 16:19:14
【问题描述】:

This 官方指南描述了如何将布尔属性绑定到 HTML 元素的禁用属性。然而,它谈到了一个控制器。

我有一个按钮,当点击该按钮时会转换路线(对不起,它必须是一个按钮,不能是一个链接):

/templates/trails.hbs

<button type="button" class="btn btn-primary" disabled={{isEditing}} 
              onclick={{route-action 'addNew'}}>Add New</button>

(route-action 是一个助手,可以让我在路由中使用闭包动作)

/routes/trails.js

import Ember from 'ember';

export default Ember.Route.extend({
  actions: {
    addNew() {
      this.transitionTo('trails.new');
    } 
  }
});

所以,点击按钮后,路由变成了'trails.new'

/routes/trails/new.js

import Ember from 'ember';

export default Ember.Route.extend({
  isEditing: true,
});

这个属性似乎被忽略并且没有像我预期的那样被绑定。我也尝试添加一个控制器:

/controllers/trails/new.js

import Ember from 'ember';

export default Ember.Controller.extend({
  isEditing: true,
});

那么官方指南是如何建议一些似乎不起作用的东西的呢?我在这里缺少什么灰烬魔法?

【问题讨论】:

    标签: javascript ember.js binding


    【解决方案1】:

    经过一番挖掘,我发现我试图做的根本不是正确的方法。我必须添加一个控制器/trails.js 并将属性“isEditing”放入其中。

    所以我将它重构为一个组件:add-new-button。这是一种更“余烬”的方式。

    首先,我需要一个初始化器(感谢this question):

    app/initializers/router.js

    export function initialize(application) {
      application.inject('route', 'router', 'router:main');
      application.inject('component', 'router', 'router:main');
    }
    
    export default {
      name: 'router',
      initialize
    };
    

    (这会将路由器注入到组件中,因此我可以观察它的变化并“抓取”当前路由)

    我的代码重构为组件:

    app/components/add-new-button.js

    import Ember from 'ember';
    
    export default Ember.Component.extend({
      isEditing: function() {
        let currentRoute = this.get('router.currentRouteName');
        return ~currentRoute.indexOf('new');
      }.property('router.currentRouteName')
    });
    

    模板/组件/add-new-button.hbs

    <button type="button" class="btn btn-primary" disabled={{isEditing}} 
            onclick={{route-action 'addNew'}}>Add New</button>
    

    模板/trails.hbs

    {{add-new-button}}
    

    现在我可以在我的其他顶级模板上使用此按钮来触发对每个资源的新路线的路线更改(并在到达新路线时禁用该按钮)。

    注意

    return ~currentRoute.indexOf('new');
    

    正在对路由进行子字符串检查,如果发现'new'返回true,否则返回false。见this

    在 ES6 中,它可以替换为(所以我有!):

    return currentRoute.includes('new);
    

    【讨论】:

    • 我很好奇,初始化器真的有必要吗?如果是,为什么/代码的哪一部分?
    • @ChristianStengel 要更改“isEditing”值,我需要知道我是否在“新”路线上。因此 this.get('router.currentRouteName');如果没有初始化程序(将路由器注入组件 - 请记住组件与外部世界隔离),这是行不通的。也许我这样做是在“打破”这种“孤立”模式,不确定。
    • @ChristianStengel 另外,请阅读我在开始时链接到的问题(有关获取当前路线的更多信息)。如果您尝试手动执行此操作(即没有初始化程序注入路由器),那么通常您的组件加载,看到路由更改,工作,然后停止看到任何进一步的路由更改,因此组件被“锁定”到第一个状态。
    【解决方案2】:

    您的模板是templates/trails.hbs,但您在子路由控制器controllers/trails/new.js 中设置了isEditing

    你需要有controllers/trails.js和deinfe isEditing

    所以在routes/trails.js 中实现这个:

    actions: {
        willTransition: function(transition) {
          if(transtions.targetName === 'trails.new'){
            this.controller.set('isEditing', true);
          }
          else{
            this.controller.set('isEditing', false);
          }
        }
      }
    

    【讨论】:

    • 啊哈-当您提供此答案时,我正在重构为一个组件(这是正确的,因为它确实回答了我正在尝试做的事情)。但我认为该组件是做到这一点的面向未来的方式。所以感谢您的解决方案,只是晚了几分钟!
    • @rmcharry 绝对是组件更好。我只是为您的问题提供答案。我应该提到,最佳实践是有能力的
    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 2015-11-04
    • 1970-01-01
    • 2018-11-20
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 2012-12-27
    相关资源
    最近更新 更多