【问题标题】:Update Route Model from Component从组件更新路由模型
【发布时间】:2017-05-24 20:54:55
【问题描述】:

我是 Ember.js 的新手,我正在尝试使用他们的 API 创建一个模仿 Youtube 的应用程序。目前我有一条路线负责从 Youtube Api 获取初始信息以填充加载页面。我有一个搜索栏组件,用于收集用户的输入并使用基于字符串的结果重新填充列表。问题是,当我从用户那里获取输入时,我的 Route 模型没有刷新以从 api 获取更新数据。下面是我的代码。

我的视频路由 video.hbs 的模板:

// app/templates/video.hbs
<div class="row">
  {{search-bar}}
<div class="row">
  <div class="col-md-12">
    <hr>
    <br>
  </div>
</div>
<div class="row">
  <div class="col-md-8">
    <div class="row">
      {{video-list model=model}}
        <div class="col-md-4 pull-right video-container">
          {{#if  videoId}}
            <iframe id="video-player" src="https://www.youtube.com/embed/{{videoId}}"></iframe>
          {{else}}
            <iframe id="video-player" src="https://www.youtube.com/embed/kEpOF7vUymc"></iframe>
          {{/if}}
        </div>
      </div>
    </div>
  </div>
</div>

我的搜索栏模板

// app/templates/components/search-bar.hbs
<div class="col-md-12 col-md-offset-4">
    <form class="form-inline">
      <div class="form-group" onsubmit="return false">
        {{input type="text" class="form-control" value=search id="search" placeholder="Search Videos..."}}
      </div>
      <button type="submit" {{action "updateSearch"}}class="btn btn-success">Search</button>
    </form>
</div>

我的搜索栏组件

// app/components/search-bar.js
import Ember from 'ember';

export default Ember.Component.extend({
  userSearch: "",
  actions: {
    updateSearch: function() {
      this.set("userSearch", this.get("search"));
      this.modelFor("videos").reload();
    }
  }
});

视频路线

// app/routes/video.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    var userSearch = this.get("search") === undefined ? "Code" : this.get("search");
    this.set("search", userSearch);
    var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&q="+ userSearch +"&maxResults=50&key="api key goes here";
    return Ember.$.getJSON(url).then(function(data) {
      return data.items.filter(function(vid) {
        if(vid.id.videoId) {
          return vid;
        }
      });
    });
  }
});

【问题讨论】:

    标签: javascript ember.js youtube frameworks components


    【解决方案1】:

    reload - 不会调用模型钩子方法,在这种情况下,您可以将动作发送到视频路由并从那里尝试refresh

    编辑:

    根据您的用例调整您的代码,如果它不起作用或这种方法有什么问题,请告诉我。

    app/routes/video.js
    这里我们使用 RSVP.hash 函数返回multiple model。我也包括userSearch。对于这个用例最好实现query parameters,但我没有使用它就实现了。

    import Ember from 'ember';
    
    export default Ember.Route.extend({
        userSearch: '',
        model: function() {
            var userSearch = this.get("userSearch") === undefined ? "Code" : this.get("userSearch");
            var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + userSearch + "&maxResults=50&key=apikey";
            return Ember.RSVP.hash({
                videosList: Ember.$.getJSON(url).then(function(data) {
                    return data.items.filter(function(vid) {
                        if (vid.id.videoId) {
                            return vid;
                        }
                    });
                }),
                userSearch: userSearch
            });
        },
        actions: {
            refreshRoute(userSearch) {
                this.set('userSearch',userSearch);
                this.refresh();
            },
        }
    });
    

    app/controllers/viedo.js
    它包含 refreshRoute 函数,这将调用视频路由文件中可用的 refreshRoute 函数。

    import Ember from 'ember';
    export default Ember.Controller.extend({
      actions:{
          refreshRoute(userSearch){
              this.sendAction('refreshRoute',userSearch);
          }
      }
    });
    

    app/templates/video.hbs
    1. 我将userSearch 属性和refreshRoute 动作名称传递给搜索栏组件
    2. 使用model.videosList访问videosList

    <div class="row">
      {{search-bar userSearch=model.userSearch refreshRoute="refreshRoute"}}
    <div class="row">
      <div class="col-md-12">
        <hr>
        <br>
      </div>
    </div>
    <div class="row">
      <div class="col-md-8">
        <div class="row">
          {{video-list model=model.videosList}}
            <div class="col-md-4 pull-right video-container">
              {{#if  videoId}}
                <iframe id="video-player" src="https://www.youtube.com/embed/{{videoId}}"></iframe>
              {{else}}
                <iframe id="video-player" src="https://www.youtube.com/embed/kEpOF7vUymc"></iframe>
              {{/if}}
            </div>
          </div>
        </div>
      </div>
    </div>
    

    app/components/search-bar.js
    在这里,您将获得 userSearch 属性作为外部属性,即。它将作为包含组件的参数传递。

    import Ember from 'ember';
    export default Ember.Component.extend({
        userSearch:'',//external attributes
        actions: {
            updateSearch() {
                var userSearch = this.get('userSearch');
                this.sendAction('refreshRoute',userSearch); //this will call corresponding controller refreshRoute method
            }
        }
    });
    

    app/templates/components/search-bar.hbs

    <div class="col-md-12 col-md-offset-4">
        <form class="form-inline">
          <div class="form-group" onsubmit="return false">
            {{input type="text" class="form-control" value=userSearch id="search" placeholder="Search Videos..."}}
          </div>
          <button type="submit" {{action "updateSearch"}}class="btn btn-success">Search</button>
        </form>
    </div>
    

    【讨论】:

    • 我之前尝试过。整个页面将重新加载,用户输入将丢失。
    • refresh 将触发 beforeModel、model 和 afterModel 钩子。然后数据将在模板中更新。看起来您的代码与 searchuserSearch 属性几乎没有混淆,这可能是用户输入丢失的原因。您可能需要引入 queryParam 进行搜索
    • 我的理解是我从输入中获取值并将该值设置为 userSearch 属性。我的期望是正确的还是我在做不同的事情?
    • 是的,你是对的。那么您是否期望userSearch 可以在routes/video.js 文件中使用?我无法理解模型挂钩中的代码this.set("search", userSearch)
    • 我认为它可以在 routes/video.js 上使用。它会看到发生了变化,然后刷新模型以从 api 获取新结果。我认为“搜索”是全局的,因此可以在模型中设置。
    猜你喜欢
    • 2016-04-20
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 2017-09-13
    • 2018-02-20
    相关资源
    最近更新 更多