1

I'm trying to make an MVC in javascript.

Model :

function Model() {
    this._productsList = [];
    this._suppliersList = [];
}

View :

function View(model) {
    this._model = model;
    this._drawLogin();
    this._drawBoard;
    this._drawAddForm;
}

Controller :

function Controller(view, model) {
    this._view = view;
    this._model = model;
}

I set them in this order :

var model = new Model();
var view = new View(model);
var controller = new Controller(view, model);

In my view i'd like to iterate through my suppliersList :

this._model._suppliersList.forEach(function(supplier) {
    $('#supplier-select').append('<option class="supplier-option" value="' + supplier.name + '">' + supplier.name + '</option>');
})

When i console.log(this._model) in my View constructor, it returns :

Object { _productsList: Array[0], _suppliersList: Array[0] }

In my view i have a function ._drawAddForm. I'd like to fetch my model suppliersList :

this._model._suppliersList.forEach(function(supplier) { console.log(supplier) });

I got an error message : this._model is undefined. I don't understand why, could someone help me understand ?

Full view page below :

function View(model) {
    this._model = model;
    this._drawLogin();
    this._drawBoard;
    this._drawAddForm;
}

View.prototype._drawLogin = function() {
    $('#header').empty();
    $('#header').append('<input class="loginField" id="loginName" type="text" placeholder="Utilisateur">');
    $('#header').append('<input class="loginField" id="loginPass" type="password" placeholder="Mot de passe">');
    $('#header').append('<span id="lockIcon" class="ui-icon ui-icon-locked"></span>');
    $('#header').append('<div id="loginError"></div>');
    $('body').append('<div id="board"></div>');
    $('#lockIcon').hover(
      function() {
        $(this).attr('class','ui-icon ui-icon-unlocked');
      }, function() {
        $(this).attr('class','ui-icon ui-icon-locked');
      }
    )
    $('#lockIcon').click(function(){
        tryLogin();
    });
}

View.prototype._drawBoard = function () {
    $('#board').remove();
    $('body').append('<div id="board"></div>');
    $('#board').addClass('animated fadeIn');

    /* Display the header */
    $('#board').append('<div id="board-header"></div>');
    $('#board-header').append('<div class="product-header-field" id="product-header-id">Identifiant produit</div>');
    $('#board-header').append('<div class="product-header-field" id="product-header-stock">Stock disponible</div>');
    $('#board-header').append('<div class="product-header-field" id="product-header-condition">État</div>');
    $('#board-header').append('<div class="product-header-field" id="product-header-new">Usure</div>');
    $('#board-header').append('<div class="product-header-field" id="product-header-from">Provenance</div>');

    /* Display products */
    $('#board').append('<div id="board-products"></div>');

    /* Add product button */
    $('#board').append('<div id="add-product-button">Ajouter un article</div>');
    $('#add-product-button').click(this._drawAddForm);
}

View.prototype._updateLogin = function(data) {
    if (data!='success') {
        $('#loginError').append('Utilisateur ou mot de passe incorrect');
    }
    else {
        $('#header').empty();
        $('#header').append('<span id="lockIcon" class="ui-icon ui-icon-unlocked"></span>');
        $('#lockIcon').hover(function() {
            $(this).attr('class','ui-icon ui-icon-locked');
            }, function() {
                $(this).attr('class','ui-icon ui-icon-unlocked');
            })
            $('#lockIcon').click(function(){
                this._drawLogin();
            });
        this._drawBoard();

    }
}

View.prototype._drawAddForm = function () {
    var radioInputs;
    $('#board').append('<div id="product-form"></div>');
    $('#product-form').append('<div id="product-form-title">Formulaire : Ajout de produit</div>');
    $('#product-form').append('<hr width="50%">');

    /* supplier form*/
    $('#product-form').append('<div id="supplier-form"></div>');
    $('#supplier-form').append('<div id="supplier-form-box"></div>')
    $('#supplier-form-box').append('<div id="supplier-form-typo">Informations fournisseur</div>');
    $('#supplier-form-box').append('<div id="supplier-form-select"></div>');
    $('#supplier-form-select').append('<select id="supplier-select"></select>');
    $('#supplier-select').append('<option class="supplier-option" value="" disabled selected>Renseignez un fournisseur</option>');
    this._model._suppliersList.forEach(function(supplier) {
        $('#supplier-select').append('<option class="supplier-option" value="' + supplier.name + '">' + supplier.name + '</option>');
    })
    $('#supplier-select').append('<option class="supplier-option" value="newsupplier">Ajouter un nouveau fournisseur</option>');
    $('#supplier-form').append('<div id="supplier-form-new"></div>');
    $('#supplier-select').change(function() {
        if ($(this).val()=='newsupplier') {
            $('#supplier-form-new').empty();
            $('#supplier-form-new').append('<div class="supplier-form-field"><div class="supplier-form-typo">Nom du fournisseur</div><input id="supplier-form-name" class="input-supplier-field" type="text" placeholder="Nom du fournisseur"></div>');
            radioInputs = '<div class="radio-box"><div class="radio-option"><input id="supplier-form-type" name="supplier-form-type" type="radio" value="individual"><div class="radio-value">Particulier</div></div>';
            radioInputs += '<div class="radio-option"><input id="supplier-form-type" name="supplier-form-type" type="radio" value="professional"><div class="radio-value">Professionnel</div></div></div>';
            $('#supplier-form-new').append('<div class="supplier-form-radio"><div class="supplier-radio-typo">Particulier/Professionnel</div>' + radioInputs + '</div>');
            $('#supplier-form-new').append('<div class="supplier-form-field"><div class="supplier-form-typo">Téléphone</div><input id="supplier-form-phone" class="input-supplier-field" type="text" placeholder="Téléphone"></div>');
            $('#supplier-form-new').append('<div class="supplier-form-field"><div class="supplier-form-typo">Adresse founrisseur</div><input id="supplier-form-adress" class="input-supplier-field" type="text" placeholder="Adresse du fournisseur"></div>');
        } 
        else {
            $('#supplier-form-new').empty();
        }
    })

    /* product form */
    $('#product-form').append('<div id="product-form-details">Informations produit</div>');
    $('#product-form').append('<div class="product-form-field"><div class="product-form-typo">Identifiant produit</div><input id="product-form-id" class="input-product-field" type="text" placeholder="Identifiant produit"></div>');
    $('#product-form').append('<div class="product-form-field"><div class="product-form-typo">Stock initial</div><input id="product-form-stock" class="input-product-field" type="text" placeholder="Stock initial"></div>');
    radioInputs = '<div class="radio-box"><div class="radio-option"><input id="product-form-condition" name="product-form-condition" type="radio" value="broken"><div class="radio-value">Défectueux</div></div>';
    radioInputs += '<div class="radio-option"><input id="product-form-condition" name="product-form-condition" type="radio" value="functional"><div class="radio-value">Commercialisable</div></div></div>';
    $('#product-form').append('<div class="product-form-radio"><div class="product-radio-typo">État</div>' + radioInputs + '</div>');
    radioInputs='<div class="radio-box"><div class="radio-option"><input id="product-form-new" name="product-form-new" type="radio" value="used"><div class="radio-value">Occasion</div></div>';
    radioInputs += '<div class="radio-option"><input id="product-form-new" name="product-form-new" type="radio" value="new"><div class="radio-value">Neuf</div></div></div>';
    $('#product-form').append('<div class="product-form-radio"><div class="product-radio-typo">Neuf/Occasion</div>' + radioInputs + '</div>');
    $('#product-form').append('<div class="product-form-field"><div class="product-form-typo">Provenance</div><input id="product-form-from" class="input-product-field" type="text" placeholder="Provenance"></div>');

    /* change add product button */
    $('#add-product-button').text('Valider le formulaire');
    $('#add-product-button').off();
    $('#add-product-button').click(function() {
        fieldList = [];
        fieldList.push(
                $('#supplier-select').val(),
                $('#supplier-form-name').val(),
                $('#supplier-form-type').val(),
                $('#supplier-form-phone').val(),
                $('#supplier-form-adress').val(),
                $('#product-form-id').val(),
                $('#product-form-stock').val(),
                $('#product-form-condition').val(),
                $('#product-form-new').val(),
                $('#product-form-from').val()       
        )
        submitNewProduct(fieldList);
    })
}
5
  • this is magical, and without seeing the context in which this._model._suppliersList.forEach(function(supplier) { console.log(supplier) }); function is scoped in, its hard to say what's being done wrong Commented Feb 28, 2016 at 9:45
  • Yes i wasn't accurate sorry. View.prototype._drawAddForm = function () { this._model._suppliersList.forEach(function(supplier) { my function }) Commented Feb 28, 2016 at 9:50
  • also could you link the exact error message, I don't really see anything wrong here. Commented Feb 28, 2016 at 10:01
  • Can you tell me how you invoke _drawAddForm? Do you assign it to some variable and use it then? like var draw = view._drawAddForm; draw(); Commented Feb 28, 2016 at 10:49
  • Yes @AmmarHasan i added the whole view page. The _drawAddForm is call'd through a click event (set inside the ._drawBoard function). Also the full msg error : TypeError: this._model is undefined Commented Feb 28, 2016 at 11:59

1 Answer 1

1

You should do replace

$('#add-product-button').click(this._drawAddForm);

with

$('#add-product-button').click(this._drawAddForm.bind(this));

or

$('#add-product-button').click($.proxy(this._drawAddForm, this));

Why? because this._drawAddForm is passed in a variable, and when such thing is done, then the context of method (i.e. this) loses its identity and forms another identity. Use .bind if it's available or otherwise use $.proxy, both do the same thing, the forcefully bind this to the function _drawAddForm.

Visit this link for a deeper understanding of what's going on. 10-most-common-javascript-mistakes

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.