ember-cli如何从控制器中实例化视图

时间:2015-04-14 17:11:40

标签: ember.js ember-cli

我正在构建地图单页应用。我希望能够向GEOJson数据检索的地图添加或删除对象。

其中一些对象将显示为< div>
因此,这些对象不是从模板生成的,而是需要在其他地方实例化。我一直在考虑负责解析GEOJson数据的控制器。

到目前为止我做了什么?

查看

//app/views/map-popup.js
import Ember from 'ember';

export default Ember.View.extend({
  templateName: "mapPopup",
  classNames: ["map-popup"]
});

模板

// app/templates/map-popup.js
<a class="popup-closer" {{action 'closePopup'}}></a>
<div class="popup-header">{{header}}</div>
<div class="popup-content">{{body}}</div>

控制器

//app/controllers/map-popup.js
/**
 * Created by alex on 13/04/2015.
 */
import Ember from 'ember';

export default Ember.ObjectController.extend({
  needs: ['map'],
  feature: null,
  header: null,
  body: null,
  overlay: null,

  /**
   * Create an overlay to anchor the popup to the map.
   */
  createOverlay: function() {
    return new ol.Overlay(/** @type {olx.OverlayOptions} */ ({
      autoPan: true,
      autoPanAnimation: {
        duration: 250
      }
    }));
  },

  hide: function() {
    this.overlay.setPosition(undefined);
  },

  addToMap: function() {
    var map = this.get('controllers.map.map');
    this.overlay = this.createOverlay();
    map.addOverlay(this.overlay);
  },

  actions: {
    closePopup: function() {
      this.hide();
    }
  }
});

我在控制器中想到这样的事情:

//app/controllers/map-draw.js
//... some code ...//
var popup = this.get('mapPopup').create({feature: this.sketch});
this.get('popups').pushObject(popup);
popup.addToMap();
//... some more code ...//

我已经阅读了很多关于依赖注入,查找等的内容。

后者很有希望,但我发现创建一个初始化器以在单个控制器中注入视图有点过分。你觉得怎么样?

编辑:有些尝试使用第4种解决方案

我添加了初始化程序:

//app/initializers/map-popup-service.js

export function initialize(container, application ) {
  application.inject( 'controller:map-draw', 'mapPopup', 'view:map-popup' );
}

export default {
  name: 'map-popup-service',
  initialize: initialize
};

当我在地图绘制控制器中放置一个断点时:

//app/controllers/map-draw.js
var popup = this.get('mapPopup').create({feature: this.sketch});

我可以获得弹出窗口(调试器):

debug (this.get('mapPopup')

我可以创建元素: createElement

但是如果我试图获取视图控制器,它还没有被注入: get('controller')

我试图在ma-draw控制器中多次调用get(&#39; mapPopup&#39;)但我总是得到相同的视图实例(相同的id)

我会尝试在渲染助手中看到控制器注入的工作原理......

编辑:阅读ember.js源代码的一些输入

文件中的

ember.js / packages / ember-application / lib / system / application.js

    ```javascript
    App.inject(<full_name or type>, <property name>, <full_name>)
    App.inject('route', 'source', 'source:main')
    App.inject('route:application', 'email', 'model:email')
    ```
    It is important to note that injections can only be performed on
    classes that are instantiated by Ember itself. Instantiating a class
    directly (via `create` or `new`) bypasses the dependency injection
    system.
    **Note:** Ember-Data instantiates its models in a unique manner, and consequently
    injections onto models (or all models) will not work as expected. Injections
    on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
    to `true`.
    @method inject
    @param  factoryNameOrType {String}
    @param  property {String}
    @param  injectionName {String}
  **/
  inject() {
    this.registry.injection(...arguments);
  },

这条线特别给了我一个很大的暗示:

  

直接实例化一个类(通过createnew)绕过依赖注入系统。

我尝试在控制器中导入视图: 从&#39; ../ views / map-popup&#39;;

导入MapPopup

我实例化了弹出窗口:

var popup = MapPopup.create({feature: this.sketch});

现在,每次调用 create 时,我都会获得一个新的视图实例 我仍然没有控制器......

编辑:阅读渲染助手后 我设法像这样设置map-popup控制器:

//app/controller/map-draw.js
var popup = MapPopup.create({feature: this.sketch});
var controller = this.container.lookup('controller:map-popup');
controller.setProperties({
  target: this,
  parentController: this
});
popup.set('controller', controller);

现在,我可以通过弹出控制器调用任何函数,但我根本不喜欢它。我很乐意,如果有一个熟悉ember.js的人可以在我打电话给控制器工厂以获得控制器的不同实例之前指导我这个...

编辑:我能提出的最佳解决方案

看完之后:

  

如果要在parentView的上下文之外创建视图(这个   可能不推荐,但它正在发生)你会想要   一定要通过容器本身实例化你的视图。

     

this.container.lookup(&#39; view:apple&#39;)//将提供一个实例   苹果观点。

stefanpenner / default_container_deprecation.md

我进入源代码并阅读:

 /**
    Given a fullName return a corresponding instance.

    The default behaviour is for lookup to return a singleton instance.
    The singleton is scoped to the container, allowing multiple containers
    to all have their own locally scoped singletons.

    ```javascript
    var container = new Container();
    container.register('api:twitter', Twitter);

    var twitter = container.lookup('api:twitter');

    twitter instanceof Twitter; // => true

    // by default the container will return singletons
    var twitter2 = container.lookup('api:twitter');
    twitter2 instanceof Twitter; // => true

    twitter === twitter2; //=> true
    ```

    If singletons are not wanted an optional flag can be provided at lookup.

    ```javascript
    var container = new Container();
    container.register('api:twitter', Twitter);

    var twitter = container.lookup('api:twitter', { singleton: false });
    var twitter2 = container.lookup('api:twitter', { singleton: false });

    twitter === twitter2; //=> false
    ```

    @method lookup
    @param {String} fullName
    @param {Object} options
    @return {any}
  */
  lookup: function(fullName, options)

我最终在我的控制器中执行此操作:

//app/contorllers/map-draw.js
var popup = _this.container.lookup('view:map-popup', { singleton: false });
var ctrl = _this.container.lookup('controller:map-popup', { singleton: false });
popup.set('controller', ctrl);
popup.createElement(); // create the div element

singleton:false 非常重要,如果没有它,所有弹出窗口都会呈现相同的内容(最后添加的内容)

编辑我发现了儿童观点,今天可能会看一眼

Understanding the view layers

0 个答案:

没有答案