简体   繁体   中英

Rails webpack js and refresh on ajax

I have a calendar module rendered in webpack js - app/javascript/packs/application.js

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new Calendar(calendarEl, {
    plugins: [ interactionPlugin, dayGridPlugin, timeGridPlugin, listPlugin, momentPlugin ],
    header: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
    },
    defaultDate: '2018-01-12',
    navLinks: true, // can click day/week names to navigate views
    editable: true,
    eventLimit: true, // allow "more" link when too many events
    selectable: true,
    events: '/events.json',
    select: function(info) {
      $.getScript('/events/new', function(){
        $('#event_date_range').val(moment(info.start).format('YYYY-MM-DD HH:mm') + ' - ' + moment(info.end).format('YYYY-MM-DD HH:mm'));
        $('#start_date').val(moment(info.start).format('YYYY-MM-DD HH:mm'));
        $('#end_date').val(moment(info.end).format('YYYY-MM-DD HH:mm'));
      });
    }
  });

  calendar.render();
});

I have a create action and would like to re-render the calendar on successful callback - create.js.erb . How can I do this?

Note: I'm assuming you're using Rails 6. I'm also assuming you added format.js to your create action.

Forget about create.js.erb , you won't need it here.

Also, you shouldn't put your code in app/javascript/packs/application.js .

The comments in that file read:

This file is automatically compiled by Webpack, along with any other files present in this directory . You're encouraged to place your actual application logic in a relevant structure within app/javascript and only use these pack files to reference that code so it'll be compiled.

This is how you would structure it:

  1. Create the folder app/javascript/calendar and inside that folder, create a file index.js with your code in it:

// import your calendar object (put it in a file calendar.js in the same folder)
import Calendar from './calendar';

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new Calendar(calendarEl, {
    plugins: [ interactionPlugin, dayGridPlugin, timeGridPlugin, listPlugin, momentPlugin ],
    header: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
    },
    defaultDate: '2018-01-12',
    navLinks: true, // can click day/week names to navigate views
    editable: true,
    eventLimit: true, // allow "more" link when too many events
    selectable: true,
    events: '/events.json',
    select: function(info) {
      $.getScript('/events/new', function(){
        $('#event_date_range').val(moment(info.start).format('YYYY-MM-DD HH:mm') + ' - ' + moment(info.end).format('YYYY-MM-DD HH:mm'));
        $('#start_date').val(moment(info.start).format('YYYY-MM-DD HH:mm'));
        $('#end_date').val(moment(info.end).format('YYYY-MM-DD HH:mm'));
      });
    }
  });

  // actually, you want to put that addEventListener on your form
  // more on 'ajax:success': https://guides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  document.body.addEventListener('ajax:success', function(event) {
    var detail = event.detail;
    var data = detail[0], status = detail[1], xhr = detail[2];

    if (status === 'OK') { // upon success
      // do something
      // re-render the calendar
      calendar.render();
    }
  })

  calendar.render();
});

Note the part I added:

  // actually, you want to put that addEventListener on your form
  // more on 'ajax:success': https://guides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  document.body.addEventListener('ajax:success', function(event) {
    var detail = event.detail;
    var data = detail[0], status = detail[1], xhr = detail[2];
    if (status === 'OK') { // upon success
      // do something
      // re-render the calendar
      calendar.render();
    }
  })

Next, you create your pack file app/javascript/packs/calendar.js and inside it, you just reference your module like so:

// importing calendar module
import '../calendar';

Now Webpack will compile your file automatically.

What's left is using the helper javascript_pack_tag that adds a script tag that references the named pack file compiled by webpack: <%= javascript_pack_tag 'calendar' %> . Add this at the bottom of your view file (for example index.html.erb).

Hope this helps.

You can use addEvent method to add the new event to the calendar

https://fullcalendar.io/docs/event-object

https://fullcalendar.io/docs/Calendar-addEvent-demo

in the success callback of create action

$.ajax({
  ...
}).done(function (response) {
  // Add event to calendar
  calendar.addEvent({
    title:  response.title,
    start:  response.start_date,
    end:    response.end_date,
    allDay: response.all_day
  })
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM