Search code examples
javascriptvalidationparsley.jsparsley

Validate dynamically created field with parsley.js


I created a form using Backbone, Marionette and Parsley.js where I can add input dynamically. But when I add a new field, parsley data-parsley-trigger doesn't seems validating field on focusout (I think because input were created after parsley initialisation). But validation works when I click on validate (because parsley() is called on whole form)

So, how to handle new field validation based on their attributes and use validation events (trigger) ?

MyApp = new Backbone.Marionette.Application;
MyApp.addInitializer(function(options) {
  var vent = new Backbone.Wreqr.EventAggregator();
  var layout = new AppLayout();
  MyApp.addRegions({
    appRegion: '#page'
  });
  MyApp.appRegion.show(layout);

  var collection = new ScheduleCollection();
  var scheduleLayout = new ScheduleLayout({
    vent: vent,
    collection: collection
  });
  layout.main.show(scheduleLayout);
});

var AppLayout = Backbone.Marionette.LayoutView.extend({
  template: "#app-layout-template",
  regions: {
    main: "#main",
    second: "#second"
  }
});

var ScheduleItemModel = Backbone.Model.extend({
  defaults: {
    date: "01/02/2016"
  }
});
var ScheduleCollection = Backbone.Collection.extend({
  model: ScheduleItemModel
});

var ScheduleItemView = Backbone.Marionette.ItemView.extend({
  tagName: "li",
  className: "sheduleblock",
  template: "#schedule-item-template",
  events: {
    "click .date": "changeDate",
    "click #remove-btn": "removeView"
  },
  modelEvents: {
    "change": "render"
  },
  changeDate: function() {
    this.model.set({
      date: "03/04/2016"
    });
  },
  removeView: function(e) {
    this.triggerMethod("remove:view", "test");
  }
});
var ScheduleLayout = Backbone.Marionette.CompositeView.extend({
  tagName: 'form',
  template: "#schedule-layout-template",
  childViewContainer: "ul",
  childView: ScheduleItemView,
  maxChildViewCount: 3,
  ui: {
    btn: '#myButton',
    submit: '#submit',
    form: 'form'
  },
  events: {
    'click @ui.btn': 'addItem',
    'click @ui.submit': 'validate'
  },
  initialize: function() {
    this.collection.set({
      'removeable': false
    });
  },
  addItem: function() {
    if (this.collection.size() < this.maxChildViewCount) {
      this.collection.add({
        removeable: true,
        viewId: this.collection.size()
      });
    }
    if (this.collection.size() >= this.maxChildViewCount) {
      this.ui.btn.prop("disabled", true)
    }
  },
  onChildviewRemoveView: function(childView, data) {
    this.collection.remove(childView.model);
    if (this.collection.size() < this.maxChildViewCount) {
      this.ui.btn.prop("disabled", false)
    }
  },
  validate: function(e) {
    e.preventDefault();
    if (this.$el.parsley().validate()) {
      alert("validation success");
    } else {
      alert("validation failed");
    }
  },
  onRender: function() {
    this.$el.parsley();
  }
});

MyApp.start();
body {
  margin: 0
}
.sheduleblock {
  border: solid 1px white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.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.3.3/backbone.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/2.4.5/backbone.marionette.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/parsley.js/2.3.9/parsley.min.js"></script>

<div id="page"></div>
<script type="text/template" id="app-layout-template">
  <div id="main"></div>
  <div id="second"></div>
</script>
<script type="text/template" id="schedule-layout-template">
  <ul></ul>
  <button id="myButton" type="button">Add Date</button>
  <button type="button" id="submit">Validate</button>
</script>
<script type="text/template" id="schedule-item-template">
  Test:
  <input type="text" name="test<%- obj.viewId %>" data-parsley-required="true" data-parsley-minlength="3" data-parsley-trigger="focusout" />
  <% if(obj.removeable===true) { %>
    <button id="remove-btn">Remove</button>
    <% } %>
</script>


Solution

  • It's true it could be easier and more documented. Easiest way currently is probably to ask Parsley if the form is valid after you've added a form element: $('.your-form').parsley().isValid().