如何在Ember.js中的控制器之间进行通信 [英] How to communicate between controllers in Ember.js

查看:78
本文介绍了如何在Ember.js中的控制器之间进行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个页面,在左边我有固定的视图(一些过滤器),适用于右边的结果。

I'd like to create a page where on the left I have fixed view (some filters) which are applied to results on the right.

例如左边是通过流派,标题,创作年份过滤电影的过滤器....
右边是不同的图表,它根据所选的过滤器进行更新。

For example on the left are filters to filter movies by genre, title, year of creation.... On the right are different charts and tables, which update based on the filters selected.

所以我想在左边有一个固定的视图,然后在右边一个根据路线改变的插座。

So I was thinking of having a fixed view on the left, then on the right an outlet which would change based on the route.

这是正确的方式如果是,我不知道如何向右侧的控制器传递过滤器更改。

Is this the correct way? If it is, I can't figure out how to communicate filter changes to controller on the right.

此JSFiddle显示类似的设置: http://jsfiddle.net/DEHcK/2/

This JSFiddle shows a similar setup : http://jsfiddle.net/DEHcK/2/

在ContentRoute - > setupController我得到一个NavigationController的实例,但是我不知道如何更改someValue。

In the ContentRoute -> setupController I get an instance of NavigationController, but then I can't figure out how to get changes to someValue.

在上面的例子中,ContentController如何获取NavigationController中的someValue的更改?

In the example above, how can ContentController get the changes to someValue in NavigationController?

这是实现我在ember中描述的应用程序的正确方法吗?

Is this the correct way to implement the app I described in ember?

JavaScript:

JavaScript:


    window.App = Ember.Application.create();

    App.Router.map(function () {
        this.route('content');
    });

    App.ContentRoute = Ember.Route.extend({
        setupController: function (controller) {
            controller.set('navigationController', this.controllerFor('navigation'));
        }
    });

    App.ContentController = Ember.ObjectController.extend({
        navigationController: null,
        observerOfSomeValue: function () {
            this.set('observedValue', this.get('navigationController.someValue'));
        }.observes('navigationController', 'navigationController.someValue'),
        observedValue: null
    });

    App.IndexRoute = Ember.Route.extend({
        redirect: function () {
            this.transitionTo('content');
        }
    });

    App.NavigationView = Ember.View.extend({
        init: function () {
            this._super();
            this.set('controller', this.get('parentView.controller').controllerFor('Navigation'));
        },
        templateName: "navigation"
    });

    App.NavigationController = Ember.ObjectController.extend({
        someValue: 'xx',
        observedValue: null,
        observerOfSomeValue: function () {
            this.set('observedValue', this.someValue);
        }.observes('someValue')
    });

HTML:

<script type="text/x-handlebars" data-template-name="application" >
    <div>
        {{view App.NavigationView}}
    </div>
    <div>
        {{ outlet }}
    </div>
</script>

<script type="text/x-handlebars" data-template-name="navigation" >
    Change {{view Ember.TextField valueBinding="controller.someValue"}}
    <div>observed value in same view: {{controller.observedValue}}</div>
</script>

<script type="text/x-handlebars" data-template-name="content" >
    <div style="margin-top: 2em">
        observed value in another view: {{observedValue}}
    </div>
</script>


推荐答案

我已经走了,创建了一个JSFiddle ,其基本的实现是你所追求的。我认为这是值得一试的,所以你可以抓住Ember。

I've gone ahead and created you a JSFiddle with a basic implementation of what you're after. I think it's worth running through it all though so that you can get a grip of Ember.

路由器

我们正在配置我们的 IndexRoute ,此时我们将所有我们的歌曲存储在 {{outlet}}

We're just configuring our IndexRoute at this point where we store all of our songs for the {{outlet}}.

App.IndexRoute = Ember.Route.extend({
    setupController: function(controller) {
        controller.set('content', [
            Ember.Object.create({ title: 'Stairway to Heaven', genre: 'Metal' }),
            Ember.Object.create({ title: 'Ratts of the Capital', genre: 'Post Rock' }),
            Ember.Object.create({ title: 'Wonderwall', genre: 'Brit Pop' }),
            Ember.Object.create({ title: 'Last Flowers', genre: 'Indie Rock' })
        ]);
    }
});

有一个很好的机会,这个代码将被一些AJAX调用替换为你的后端红宝石/ PHP。暂时,我们将给出 IndexRoute 设置控制器的责任(因此 setupController )。这个责任也可能在控制器本身上,并且可能是抽象出AJAX调用的好主意,因为你会有很多类似的AJAX调用。

There's a good chance this code will be replaced with an AJAX call of some sort to your back-end Ruby/PHP. For the time being though, we'll give the IndexRoute the responsibility of setting up the controller (hence setupController). This responsibility could just as well lie on the controller itself, and is probably a good idea to abstract out the AJAX call since you'll have many similar AJAX calls.

你也可以决定使用Ember的DataStore ,这将会再次改变控制器的实现。

You may also decide to use Ember's DataStore, which will change the implementation of the controller again.

索引控制器

接下来,我们将设置我们的 IndexController (这是我们的 SongsController 真的),我们希望这个控制器有两个职责:

Next we're going to setup our IndexController (which is our SongsController really), we want this controller to have two responsibilities:


  1. 存储歌曲(也可以从后端获取歌曲);

  2. 根据传入其中的过滤器过滤歌曲

为此,我们创建一个计算属性过滤掉内容,因为我们不想实际

For this we create a computed property to filter out the content, since we don't want to actually manipulate the special content array directly.

App.IndexController = Ember.ArrayController.extend({
    content: [],
    excludeGenres: [],

    filteredContent: function() {
        var excludeTheseGenres = this.get('excludeGenres').mapProperty('genre');
        return this.get('content').filter(function(model) {
            return Boolean(jQuery.inArray(model.get('genre'), excludeTheseGenres) === -1);
        });
    }.property('excludeGenres.length', 'content.length')
});

excludeGenres 将采用一系列流派对象。例如,如果Post Rock包含在 excludeGenres 中,那么我们不会显示任何Post Rock相关的歌曲,但如果不存在,那么我们我们会显示他们! IndexController 没有维护这个数组的责任,但它确实有责任过滤其内容,当这个数组是更新

The excludeGenres will take an array of genre objects. For example, if "Post Rock" is contained within excludeGenres, then we won't show any "Post Rock" related songs, but if it isn't present, then we we'll show them! The IndexController doesn't have the responsibility of maintaining this array, but it does have the responsibility of filtering its content for when this array is updated.

流派控制器

也许最令人困惑控制器在我们的小应用程序中,因为它实际上没有自己的内容,而是依赖于 IndexController 的内容。

Perhaps the most confusing controller in our little application, because it doesn't actually have any content of its own, but rather depends on the IndexController's content.

App.GenresController = Ember.ObjectController.extend({
    needs: ['index'],

    genres: function() {
        return this.get('controllers.index').mapProperty('genre').uniq();        
    }.property('controllers.index.length'),

    toggle: function(genreName) {
        var indexController     = this.get('controllers.index'),
            genres              = indexController.get('excludeGenres'),
            genre               = indexController.findProperty('genre', genreName);

        if (genres.findProperty('genre', genreName)) {
            genres.removeObject(genre);
            return;
        }

        genres.pushObject(genre);
    }
});

类型控制器的职责可以这样定义:

Genre controller's responsibilities can be defined as so:


  1. 要监视 IndexController 内容数组,并获取唯一的流派名称当其长度更改时;

  2. 当用户单击列表中的类型以包含/排除它时,填充 excludeGenres 数组。

  1. To monitor the content array of the IndexController and fetch the unique genre names when its length changes;
  2. To populate the excludeGenres array when a user clicks on a genre in the list to include/exclude it.

要调用切换方法,我们需要在我们的类型视图在点击时调用它:< a {{actiontogglegenre}}> {{genre}}< / a> 。现在每当用户点击类型时,将调用切换方法,并将类型名称作为第一个参数传递。

To have the toggle method called, we need to specify an action in our genre view to invoke it when clicked: <a {{action "toggle" genre}}>{{genre}}</a>. Now whenever a user clicks on a genre, the toggle method will be invoked, and the genre name passed as the first argument.

一旦我们进入切换方法,它将确定类型是否已被排除。如果被排除,那么它将被删除,反之亦然。一旦我们添加/删除了类型, filteredContent 计算的属性将被再次触发,索引视图将无缝更新。

Once we're in the toggle method, it will determine whether the genre is already being excluded. If it is being excluded, then it will be removed, and vice-versa. Once we've added/removed the genre, the filteredContent computed property will be fired again, and the index view will be updated seamlessly.

GenresController 实际上没有自己的内容的原因是管理两个内容似乎很愚蠢c $ c>数组时,两者有关系。由于流派可以通过应用程序中的歌曲来确定,所以控制器可以从该列表中收集信息,并且只需拉出所需的信息 - 在我们的例子中,类型。

The reason the GenresController doesn't actually have its own content is that it would seem silly to manage two content arrays when the two have a relationship. Since genres can be determined from the songs present in the application, the controller can gather the information from that list, and just pull out the information it requires -- in our case, genres.

这样,如果添加/删除歌曲,那么类型列表可以保持同步。

This way, if a song is added/removed, then the genre list can be kept in sync.

结论

然而,我认为您的原始问题的答案是,为了使控制器相互通信,您需要指定需要什么(含需要)。

I think the answer to your original question is, however, that in order for controllers to be communicating with one another, you need to be specifying what it needs (with needs).

这篇关于如何在Ember.js中的控制器之间进行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆