vendredi 17 juin 2016

EmberJS advice on controller, service and component usage

I'm trying to figure out how to properly handle the communication between a controller and several components. I think I need to use a service here, but maybe another solution would me more appropriate.

The idea is that users get served a lesson where one question is given. When a user clicks on the check button, a request to the backend API should be made to check whether an answer is correct. The tricky part is that questions can have different types: open questions, multiple choice and drag and drop.

There is a /lesson/template.hbs which summarized looks like this:

// lesson/template.hbs
<h2></h2>

<div class="callout"> } </div>


    

    

    



<a class="next button" >Next</a>

<a class="check button" >Check</a>


Then, my idea was to have a lesson/controller.js which handles the both the nextQuestion and checkAnswer click actions:

// lesson/controller.js
export default Ember.Controller.extend(Ember.Evented, {

    lesson: Ember.inject.service(),

    errorObserver: Ember.on('init', Ember.observer('lesson.has_error', function() {
        console.log('Error detected');
    })),

    actions: {
        checkAnswer() {
            this.set('lesson.is_check_pressed', true);
        }
    }

});

And to have a service who is responsible for glueing the controller and corresponding component:

// lesson/service.js
export default Ember.Service.extend({

    is_check_pressed: false,
    has_error: false,

    checkObserver: Ember.observer('is_check_pressed', function() {
        console.log('LessonService: Observer: is_check_pressed changed to', this.get('is_check_pressed'));
    }),

    errorObserver: Ember.on('init', Ember.observer('has_error', function() {
        console.log('LessonService: Observer: has_error changed');
    })),

});

This service, in the end, will also contain an ajax request to the backend api.

And, for example, the answer-open-textarea component looks as follows:

export default Ember.Component.extend({

    lesson: Ember.inject.service(),
    given_answer: '',

    checkObserver: Ember.on('init', Ember.observer('lesson.is_check_pressed', function() {
        console.log('OpenTextAreaComponent, checkObserver');

        if( Ember.isBlank( this.get('given_answer') ) )
        {
            this.set('lesson.is_check_pressed', false);
            this.set('lesson.has_error', true);
        }
        else
        {
            // Update variable @ service so that the controller knows that the nextQuestion button can be active
        }
    })),

});

The logic for validating the input, should be in the component, since it does not make sense to have the validity checks for all the possible question types in the controller.

Unfortunately, the code above does not work the way it should, even though this is just the basic idea. What works is, when the check button is pressed, the component checkObserver is fired, as it logs to the console. But it does not trigger the errorObserver in the controller, when updating lesson.has_error in the service. And, even if this would work, both the controller and the component will have several obeservers which I don't feel like to be a good solution.

My question is: how can controllers and components "communicate" in a proper way? By using a service? If yes, then how would that look like? I guess not via Observers.

Thanks in advance!




Aucun commentaire:

Enregistrer un commentaire