【问题标题】:Ember: modify model in a routeEmber:修改路由中的模型
【发布时间】:2018-04-19 20:59:30
【问题描述】:

我正在开发 Ember 应用程序,但遇到了问题。我必须在应用程序的某个点过滤掉结果,比如在控制器或视图中,如下所示:

view.hbs 我正在消除{{#if test.passed}}... 通过的测试:

{{#each tests as |test|}}<br>
    {{#if test.passed}}
        {{test.name}}
    {{/if}}
{{/each}}

我可以在最初加载并可以在输入字段中过滤掉的控制器上执行此操作:

import Controller from '@ember/controller';
export default Controller.extend({
    actions: {
        filterByTest: function (param) {
            if (param !== '') {
                return this.get('store').query('test', { name: param }).then((filteredTests) => {
                    return { query: param, tests: filteredTests.filterBy('passed', true) };
                });
            } else {
                return this.get('store').findAll('test').then((tests) => {
                    return { query: param, tests: tests.filterBy('passed', true) };
                });
            }
        }
    }
});

现在我需要在route 级别进行过滤。 model() 中的 route 是无法编辑的,如果可以,那么它必须是我不想要的路径。我怎样才能做到这一点?如何使模型可编辑?目前我可以进入路线模型,但无法编辑。这是我从view.hbs 文件中与模型交谈的方式,它有效。

{{#each model as |test|}}<br>
    {{test.name}}
{{/each}}

请看下面将文件返回到上面view.hbs模板的模型。再次,它正在工作:

import Route from '@ember/routing/route';

export default Route.extend({
    model() {
        return this.get('store').findAll('test').then(tests => {
            return tests('passed', true);
        })
    }
});

如何将参数传递给模型并对其进行编辑,以便我的 UI 也得到更改?

这是我需要修改的模型。目前return 有效,但不可修改。

【问题讨论】:

  • 查询中有参数的子路由呢?当您通过控制器执行此操作时,param 来自哪里?你的路线中没有那个参数吗?
  • 嗨@Jeff,感谢您的关注。我在 route->model 中没有参数。如何将参数发送到那里以及如何通过过滤掉数据来修改模型?

标签: ember.js


【解决方案1】:

如果我的理解与@Jeff 相同,您是否想根据用户通过按钮或某种方式选择的选项来查询您的后端。在这方面最好从状态的角度来考虑。控制器将有一个表示您想要表示的过滤视图的状态,并且您的 model() 挂钩将使用该状态来了解如何查询您要显示的特定模型集。

这是一个演示如何完成的工作旋转(后端使用 ember-cli-mirage):https://ember-twiddle.com/150708278ceafc6f9f99961122a14f07

重点是我的路由定义了一个queryParams 对象(与@Jeff 的答案相同),它指示路由在每次控制器上的category 属性更改时刷新其模型。

queryParams: {
  category: { refreshModel: true }
},

model() 挂钩中,我使用params.category 值来构造正确的查询负载。

model(params) {
  if (params.category === 'all') {
    return this.store.findAll('test');
  }
  let passed = params.category === 'passed';
  return this.store.query('test', { 'filter[passed]': passed });
}

最后我确保我的控制器知道 category 是从 URL 驱动的:

queryParams: ['category'],
// A default is required to train ember on how to serialize
// the value in the URL
category: 'all',

您现在可以更改category 的值,整个路线会自动为您刷新,或者您可以使用link-to 助手

<button {{action (mut category) "passed"}}>Show passed</button>
{{#link-to "index" (query-params category="passed")}}Show passed{{/link-to}}

【讨论】:

    【解决方案2】:

    嗨@AmazingDayToday ? 我将就我们如何看待您的问题以及我们将如何根据可用信息解决它进行更长时间的解释。 @Jeff 似乎已经回答了您,但希望这将有助于您了解如何考虑这些问题。

    我们的第一个假设是您希望将过滤器参数作为操作的一部分传递。在测试时,我们创建了一系列按钮,将name 属性传递给操作,如下所示

    <button {{action 'filterByTestName' 'face'}}>Face</button>
    <button {{action 'filterByTestName' 'first test'}}>First Test</button>
    <button {{action 'filterByTestName' ''}}>Clear</button>
    

    最后一个按钮旨在利用相同的操作来清除过滤器。在这些情况下,我通常倾向于创建一个单独的 clear 操作,但它现在可以工作?

    我实现这类过滤器的主要方法之一是在控制器上为相关路由设置一个filteredModel 计算属性。这个计算属性的要点是根据控制器上的“filterValue”进行过滤,该控制器可以由filterByTestName 操作设置。让我们从那里开始:

    actions: {
      filterByTestName: function(name) {
        this.set('filterValue', name);
      }
    }
    

    此操作的设计是为了在设置filterValue 时根据该值过滤模型。让我们继续讨论将为我们执行过滤器的计算属性:

    filteredModel: Ember.computed('filterValue', 'model.@each.name', function() {
      if(Ember.isEmpty(this.get('filterValue'))) {
        return this.model;
      }
    
      return this.model.filter((test) => test.get('name') === this.get('filterValue'));
    }),
    

    您会注意到该计算属性的第一件事是我们有两个依赖键,即当filterValue 或任何name 值在任何模型改变。

    此实现中要注意的第二件事是当filterValue 为空时的“基本情况”,我们希望不修改通过当前模型。

    这个实现的最后一部分是,我们要根据filterValue 的当前值对当前模型实际执行过滤器。

    您可以在 Ember Twiddle 上看到整个示例,您可以在 this YouTube video 上看到我们正在解决这个问题

    我希望这会有所帮助?

    【讨论】:

      【解决方案3】:

      这有点猜测,因为我不能 100% 确定您想要实现什么。

      我不知道param 来自哪里,但我假设有一个类似yourroute?name=TestName 的查询参数。有了这个,您可以像这样访问该参数:

      export default Route.extend({
        // if you leave that out, it'll work for the first entry, but the model will not update if you transitionToRoute with only the queryParams changed)
        queryParams: {
          category: {
            refreshModel: true
          }
        },
      
        model(params) {
          // params has format of { name: "TestName" }
          return this.get('store').query('test', params);
      
          // you can of course put more complex logic in here, as you had it in controller
          // f.e.: 
          // return this.get('store').query('test', {name: params.name, passed: true});
          // or check first if you have a param at all...
        }
      }
      

      还有here's the docs

      注意:
      您不能在控制器上设置参数来更改模型。我已经试过了......非常强烈。
      要更改它,您必须在模板中执行 {{link-to "routeName" (query-params name="newName")}} 或在控制器中执行 transitionToRoute({ queryParams: { name: 'anotherName' } }); (docs for transitionToRoute())。

      旁注:无论如何,将filterByTest 作为一个动作是很奇怪的。这应该是一个计算属性。

      【讨论】:

      • 通过向控制器添加queryParams: ['category'],该控制器上的任何设置也将触发路由上的refreshModel
      猜你喜欢
      • 1970-01-01
      • 2014-06-10
      • 2015-05-12
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 2018-05-14
      • 1970-01-01
      相关资源
      最近更新 更多