1

I'm beginning to use jquery and Model View ViewModel and I encounter a problem with the utilisation of this with the Event Handler Attachment : on(). My first class is TicTacToeModel which manipulates a TicTacToe game in memory :

var TicTacToeModel = function () {
        Observable.call(this);
        this.grid = new Array(3);
        for (let i = 0; i < this.grid.length; ++i) {
            this.grid[i] = new Array(3);
        }
    };
//Some prototype function
//...

I have another class, TicTacToeController which depends on the first class and which manages the graphic part of the game with a manipulation of the DOM :

var TicTacToeController = function(game, selector) {
        this._element = $(selector);
        this._model = game;
        this._template = Handlebars.compile(view);
        this.addListeners();
        this.render();
    };

(declaration of game : game = new TicTacToeModel();)

So in my second class I have this function :

TicTacToeController.prototype.addListeners = function() {
    this._model.on('change', this.render, this);
    this._model.play(0,0);//works
    this._element.on('click', "td", function() {
        this._model.play(0,0);//doesn't work
    });
};

And I would like to call the play() function in the cell (0,0) (the function play updates the game in memory) when I click on the cell in my graphic interface but I cannot do it in the .on(). But that seems to be working outside of the .on() function so I suppose a bad utilisation of this causing the problem.

2 Answers 2

1

You need to use bind like this.

Change this:

this._element.on('click', "td", function() {
    this._model.play(0,0);//doesn't work
});

to:

this._element.on('click', "td", function() {
    this._model.play(0,0); //should now work
}.bind(this));
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer, that works fine but if I add some jquery into the function like that : TicTacToeController.prototype.addListeners = function() { this._model.on('change', this.render, this); this._element.on('click', "td", function() { $(this).addClass("case"); $(this).html("X"); this._model.play(0,0);//doesn't work }.bind(this)); }; The jquery isn't be taken into account, have you got any idea to fix it ?
Not sure what you mean by "The jquery isn't be taken into account" but have you tried $(this._element)... instead of $(this)...?
$(this._element) doesn't work because it changes my whole grid but if I add the parameter "event" in: this._element.on('click', "td", function(event) {...}, event.target works. But why I cannot use $(this) whereas it represents the "td" element of the .on() function ?
0

You are not in the same scope, it's not the same this variable you are employing when calling the play method. A dirty workaround could be

let _model = this._model
this._element.on('click', "td", function() {
        _model.play(0,0);//work!
    });

But as said it's a dirty workaround, maybe someone else could explain but basically think this produces a memory leak. Maybe the solution would be to use a method in the same class and pass the instance to the click method, kind of:

TicTacToeController.prototype.click = function() ...
...
this._element.on('click', "td", this.click);

Think this should do the trick, but I must admit I'm not a js expert.

1 Comment

I thought to use this dirty workaround too but I knew that there was a better way to solve my problem ^^.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.