1

I have a property in the controller. I want to use a component to update that controller property. The usual component parameter passing works when I'm using a text field like the guides say, but in my case, I'm changing the value in code, not input fields. The binding seems to be broken.

What method similar to propertyDidChange() or notifyPropertyChange() should I use to accomplish this? Can you also provide a simple example so I know WHERE to make that method call?

personalities controller

`import Ember from 'ember'`

PersonalitiesController = Ember.ArrayController.extend

  eiValue: ->
    if params.name
      params.name.charAt(0)
    else
      'e'

  nsValue: ->
    if params.name
      params.name.charAt(1)
    else
      'n'

  tfValue:  ->
    if params.name
      params.name.charAt(2)
    else
      't'

  pjValue:  ->
    if params.name
      params.name.charAt(3)
    else
      'p'

  type: (->
    this.get('eiValue') + this.get('nsValue') + this.get('tfValue') + this.get('pjValue')
  ).property('eiValue', 'nsValue', 'tfValue', 'pjValue')

  typeChanged: ((model, type)->
    Ember.run.once(this, 'routeToPersonality')
  ).observes('type')

  routeToPersonality: ->
    this.get('controller').transitionToRoute('personality', this.get('type'))

`export default PersonalitiesController`

personalities template

%dichotomy-selector type=type

component

`import Ember from 'ember'`

DichotomySelectorComponent = Ember.Component.extend
  eiValue: 'e'
  nsValue: 'n'
  tfValue: 't'
  pjValue: 'p'

  type: (->
    newValue = this.get('eiValue') + this.get('nsValue') + this.get('tfValue') + this.get('pjValue')
    this.set('controller.type', newValue)
  ).property('eiValue', 'nsValue', 'tfValue', 'pjValue')

  actions: 
    toggleEI: ->
      eiValue = this.get('eiValue')
      if eiValue == 'e'
        this.set('eiValue', 'i')
      else if eiValue == 'i'
        this.set('eiValue', 'e')

    toggleNS: ->
      nsValue = this.get('nsValue')
      if nsValue == 'n'
        this.set('nsValue', 's')
      else if nsValue == 's'
        this.set('nsValue', 'n')

    toggleTF: ->
      tfValue = this.get('tfValue')
      if tfValue == 't'
        this.set('tfValue', 'f')
      else if tfValue == 'f'
        this.set('tfValue', 't')

    togglePJ: ->
      pjValue = this.get('pjValue')
      if pjValue == 'p'
        this.set('pjValue', 'j')
      else if pjValue == 'j'
        this.set('pjValue', 'p')

`export default DichotomySelectorComponent`
RustyToms
  • 7,600
  • 1
  • 27
  • 36
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85

1 Answers1

3

You should be able to use this.set("controller.property", value) in a method inside the component, per the docs here: http://emberjs.com/api/classes/Ember.Component.html#property_controller

Edit September 2016 This answer has been the victim of the ongoing evolution of Ember, and the associated changes in best practices. It is amazing to see how different Ember is from just 1.5 years ago. The old answer has been totally rejected by the community as evidenced by the votes (negative as I type this), in fact I don't think it even works anymore. As of mid-2016 in Ember 2.x the generally accepted answer to this question is to create an action in the controller that changes the property, pass that action to the component, and call the action when the value changes on the component. But now you can use the action helper to pass a regular method instead of an action, and use component life cycle hooks to detect changes in the component instead of using an observer or computed property. You could also use a service instead. More changes on the way, I am sure.

For any future readers, any questions you need to research about Ember make sure that you filter results by time, you only want results within the last year.

RustyToms
  • 7,600
  • 1
  • 27
  • 36
  • where? I don't see that anywhere. – ahnbizcad Mar 29 '15 at 02:07
  • I think maybe you have a different idea of what a component is. Can you please add your code to your question? – RustyToms Mar 29 '15 at 22:08
  • 1
    This answer has been the victim of the ongoing evolution of Ember, and the associated changes in best practices. It is amazing to see how different Ember is from just 1.5 years ago. The current answer to this question is, create an action in the controller that changes the property, pass that action to the component, call the action when the value changes on the component. But now you can use the action helper to pass a method instead of an action, and use component life cycle hooks to detect changes in the component instead of using an observer or computed property. – RustyToms Sep 26 '16 at 17:52
  • I think the api has just changed. your link links to the current version of the documentation. Here is the Ember version 1 link: https://emberjs.com/api/ember/1.13/classes/Ember.Component?show=inherited%2Cprotected%2Cprivate%2Cdeprecated though, looking at that documentation, I'm not seeing anything about a property controller at all. So.. the advice is just.. wrong? – NullVoxPopuli Sep 05 '18 at 12:51
  • 1
    @NullVoxPopuli it was correct at the time, and so was the docs link. As the edit explains, you should call an action on the component that gets caught in the controller, which will modify the controller property. The ArrayController from the original question doesn't even exist anymore, you shouldn't use .observes even if you still can. And I don't use Ember anymore, looks like Ember 3 is out, so who knows now. Though I suspect it is the same as Ember 2. Except the proper solution might be to use a service now. – RustyToms Sep 05 '18 at 21:00
  • yea, you got it. Components and Services have a very flexible and powerful relationship. Pretty much everything is done with just those two pieces. – NullVoxPopuli Sep 05 '18 at 21:12