Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
550 views
in Technique[技术] by (71.8m points)

ember.js - How to call method of a component from a controller

I have a component that represent a map and after an action in my controller I want to call a method on the component to center the map. The code looks like this

App.PlacesController = Ember.Controller.extend({
  actions : {
    centerMap : function () {
        // how to call from here to GoogleMapComponent.centerMap ??
    }
  }
});


App.GoogleMapComponent = Ember.Component.extend({
  centerMap : function () {
  }
});

template

{{google-map}}
<button {{action "centerMap"}}>Center Map</button>

I have found a workaround but I don't think this is the Ember way of doing this.

{{google-map viewName="mapView"}}
<button class="center-map">Center Map</button>

App.PlacesView = Ember.View.extend({
  didInsertElement : function () {
    this.$(".center-map").click(this.clickCenterMap.bind(this));
  },

  clickCenterMap : function () {
    this.get("mapView").centerMap();
  }
});
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In Ember, views (Components are glorified views) know about their controller, but controllers do NOT know about views. This is by design (MVC) to keep things decoupled, and so you can have many views that are being "powered" by a single controller, and the controller is none the wiser. So when thinking about the relationship, changes can happen to a controller and a view will react to those changes. So, just to reiterate, you should never try to access a view/component from within a controller.

There are a few options I can think of when dealing with your example.

  1. Make the button part of your component! Components are meant to handle user input, like button clicks, so you may want to consider making the button a part of the map component and handle clicks in the actions hash of your component. If this buttons is always going to accompany the map component, then I certainly recommend this approach.

  2. You could have a boolean property on your controller like isCentered, and when the button is clicked it's set to true. In your component you can bind to that controller's property, and react whenever that property changes. It's a two-way binding so you can also change your locally bound property to false if the user moves the map, for example.

    Controller:

    ...
    isCentered: false,
    actions: {
        centerMap: {
            this.set('isCentered', true);
        }
    }
    ...
    

    Component:

    ...
    isCenteredBinding: 'controller.isCentered',
    onIsCenteredChange: function () {
        //do your thing
    }.observes('isCentered'),
    ...
    
  3. Jeremy Green's solution can work if you mix in the Ember.Evented mixin into the controller (which adds the pub/sub trigger and on methods)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...