Only set the Backbone Model attributes of fields entered on form submit

1.3k views Asked by At

I am trying out the Backbone.StickIt plugin for data-binding, my question is on initial render I display the Model defaults name and email. If I were to enter only my name in the contact form both name and email get rerendered, how can only set the inputs whos values have been entered? So if email value === '' don't be setting/rendering this?

Fiddle: http://jsfiddle.net/kyllle/e6z7gbta/

JS

var FormView = Backbone.View.extend({

    template: _.template( $('.js-form-template').html() ),

    events: {
        'submit': 'onFormSubmit'
    },

    render: function() {
        this.$el.html( this.template( this.model.toJSON() ) );

        return this;
    },

    onFormSubmit: function(event) {
        event.preventDefault();

        var nameValue = this.$('input[id=name]').val(),
            emailValue = this.$('input[id=email]').val();

        this.model.set({
            'name': nameValue,
            'email': emailValue
        });
    }
});

var UserView = Backbone.View.extend({

    bindings: {
        '.js-name': 'name',
        '.js-email': 'email'
    },

    template: _.template( $('.js-user-template').html() ),

    render: function() {
        this.$el.html( this.template( this.model.toJSON() ) );

        this.stickit();

        return this;
    }
});

Template

<script type="text/template" class="js-user-template">
    <h1>User Details</h1>
    <p>Name: <span class="js-name"><%= name %></span></p>
    <p>Email: <span class="js-email"><%= email %></span></p>
</script>

<script type="text/template" class="js-form-template">
    <h1>Contact Form</h1>
    <form action="/">
        <fieldset>
            <label for="name">Name</label>
            <input type="text" id="name" class="form-text" />
        </fieldset>

        <fieldset>
            <label for="email">Email</label>
            <input type="email" id="email" class="form-text" />
        </fieldset>

        <fieldset class="form-actions">
            <input type="submit" value="Submit" />
        </fieldset>
    </form>
</script>
1

There are 1 answers

1
T J On

If I understood correctly, you just need to add a simple validation before setting the values to the model, rather than blindly updating the model at once :

console.clear();

// Classes
var ContactModel = Backbone.Model.extend({
  defaults: {
    'name': 'Joe Bloggs',
    'email': '[email protected]'
  }
});
var FormView = Backbone.View.extend({

  template: _.template($('.js-form-template').html()),

  events: {
    'submit': 'onFormSubmit'
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));

    return this;
  },

  onFormSubmit: function(event) {
    event.preventDefault();

    var nameValue = this.$('input[id=name]').val(),
      emailValue = this.$('input[id=email]').val();
    
    //Validate the input before setting
    if (nameValue) this.model.set({
      'name': nameValue
    });
    if (emailValue) this.model.set({
      'email': emailValue
    });
  }
});

var UserView = Backbone.View.extend({

  bindings: {
    '.js-name': 'name',
    '.js-email': 'email'
  },

  template: _.template($('.js-user-template').html()),

  initialize: function() {
    //this.listenTo(this.model, 'change:name', this.render);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));

    this.stickit();

    return this;
  }
});

// Setup
var contactModel = new ContactModel();

var formView = new FormView({
  model: contactModel
});

var userView = new UserView({
  model: contactModel
});

// Add to DOM
$('.js-ctn').append(
  userView.render().el,
  formView.render().el
);
@import url(http://fonts.googleapis.com/css?family=Roboto:300,400,500);
 body {
  font-family: Roboto;
  color: #191919;
}
a {
  color: #191919;
}
form fieldset {
  margin: 0 0 20px 0;
  font-size: 14px;
}
form fieldset.form-actions {
  margin: 0;
}
form fieldset label {
  display: block;
  margin: 0 0 5px 0;
  font-weight: bold;
}
form fieldset input.form-text {
  display: block;
  width: 50%;
  padding: 5px;
  font-size: 14px;
  border: 1px solid #ddd;
  background: #f5f5f5;
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .05);
  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .05);
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .05);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
form fieldset input.form-text:focus {
  border: 1px solid #ccc;
  background: #fff;
}
form fieldset p.form-help {
  margin: 5px 0 0 0;
  font-size: 12px;
  color: #999;
}
form input[type="submit"] {
  margin: 0;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: bold;
  border: 1px solid #ccc;
  background: #eee;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
form input[type="submit"]:hover,
form input[type="submit"]:focus {
  border: 1px solid #bbb;
  background: #e5e5e5;
}
form input[type="submit"]:active {
  border: 1px solid #ccc;
  background: #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.2/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.stickit/0.8.0/backbone.stickit.min.js"></script>
<div class="js-ctn"></div>

<script type="text/template" class="js-user-template">
  <h1>User Details</h1>
  <p>Name: <span class="js-name"><%= name %></span>
  </p>
  <p>Email: <span class="js-email"><%= email %></span>
  </p>
</script>

<script type="text/template" class="js-form-template">
  <h1>Contact Form</h1>
  <form action="/">
    <fieldset>
      <label for="name">Name</label>
      <input type="text" id="name" class="form-text" />
    </fieldset>

    <fieldset>
      <label for="email">Email</label>
      <input type="email" id="email" class="form-text" />
    </fieldset>

    <fieldset class="form-actions">
      <input type="submit" value="Submit" />
    </fieldset>
  </form>
</script>