简体   繁体   中英

ember-cli: bind template action from view created using lookup

Ember : 1.10.0

Ember Data : 1.0.0-beta.16

jQuery : 1.11.2

I'm using this.container.lookup in order to create a view dynamically in my controller like this:

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();

the view is defined like this:

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

The view template:

<a class="popup-closer" {{action 'closePopup'}}></a>
<div class="popup-content">{{content}}</div>

and the view's controller:

export default Ember.ObjectController.extend({

  hide: function() {
    console.log("i'm hidden");
  },

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

The view is inserted correctly in the DOM by my controller:

<div class="ember-view map-popup" id="ember643">
  <a data-ember-action="645" class="popup-closer"></a>
  <div class="popup-content">571187.3674937992,5721182.413928764</div>
</div>

But nothing happens when I click on the popup-closer.

I would be glad if someone could show me how to bind the action to the view's controller.

Following albert advice, I tried to setup a component:

//app/components/map-popup.js
export default Ember.Component.extend({
  classNames: ['map-popup'],
  layoutName: 'components/map-popup',

  content: function() {
    return "some content";
  },

  hide: function() {
    console.log('hidden');
  },

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

template is the same. as before, but inthe templates/components folder.

The result is worst than before. I get the popup to display the function as text instead of the content text...

在此处输入图片说明

The action is now triggered! That's great, the problem with the content not being displayed has bene solved using jquery:

  setUp: function() {
    this.$('.popup-content').html(this.content());
  }.on('didInsertElement'),

I think it's ugly, I would much rather have a one way binding the the {{content}} in handlebar... But I cannot figure out how to do this.

@albertjan is right. This has to be a component. Thats the right direction.

Now for the issue that content() is not returning values can be solved if you make a computed property for it like this

export default Ember.Component.extend({
  classNames: ['map-popup'],
  layoutName: 'components/map-popup',

  /*Notice the .property('') */
  content: function() {
    return "some content";
  }.property(''),

  hide: function() {
    console.log('hidden');
  },

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

Why this works, When you use a simple function in template its nothing more than a attribute having some string value (which is function() body)

To use the function's return value Ember use concept of computed properties.

Computed properties also accept arguments and are useful for combining results of two or more properties like this. Its output updates when any dependent properties changes.

Example can be found here on Emberjs.com

var Person = Ember.Object.extend({
  // these will be supplied by `create`
  firstName: null,
  lastName: null,

  fullName: function() {
    var firstName = this.get('firstName');
    var lastName = this.get('lastName');

   return firstName + ' ' + lastName;
  }.property('firstName', 'lastName')
});

var tom = Person.create({
  firstName: 'Tom',
  lastName: 'Dale'
});

tom.get('fullName') // 'Tom Dale'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM