我使用fullcalendar框架在日历上创建“Timeslots”。时隙与“体验”相关联。我遇到的问题是当我想从日历编辑时隙时。
FullCalendar有一个方法,允许在单击事件时进行回调,并传递该事件的所有数据。我已经构建了一个HTML表单(不使用rails form_for),这样我就可以将:id值直接注入表单中。
我可以在我的rails控制台和错误页面中看到页面上存在所有参数和id值。但是,我无法通过这个参数错误,我认为它引用了它没有收到时隙的id?任何帮助将不胜感激!!!
Rails控制台错误
app/controllers/timeslots_controller.rb:30:in `update'
Started PATCH "/experiences/3/timeslots/16" for 127.0.0.1 at 2018-04-01 12:13:04 -0700
Processing by TimeslotsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OKz4aA+GDK74dFRaO9p2WA+2fFKrKzrAAmkFLZAkgT4w0DNMPEcUpH7IJR6P/debkSjOBjkRqzBI1+nk8uvecA==", "timeslot"=>{"start_time"=>"2018-04-09 12:00 am", "end_time"=>"2018-04-09 12:00 am", "inventory"=>"4", "price"=>"120"}, "button"=>"", "experience_id"=>"3", "id"=>"16"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
Timeslot Load (0.4ms) SELECT "timeslots".* FROM "timeslots" WHERE "timeslots"."id" = $1 ORDER BY "timeslots"."start_time" ASC LIMIT $2 [["id", 16], ["LIMIT", 1]]
Experience Load (0.2ms) SELECT "experiences".* FROM "experiences" WHERE "experiences"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
CACHE Timeslot Load (0.0ms) SELECT "timeslots".* FROM "timeslots" WHERE "timeslots"."id" = $1 ORDER BY "timeslots"."start_time" ASC LIMIT $2 [["id", 16], ["LIMIT", 1]]
Completed 500 Internal Server Error in 6ms (ActiveRecord: 1.0ms)
ArgumentError (wrong number of arguments (given 0, expected 1)):
app/controllers/timeslots_controller.rb:30:in `update'
timeslots_controller.rb
class TimeslotsController < ApplicationController
before_action :set_timeslot, only: [:edit, :update]
def create
experience = Experience.find(params[:experience_id])
start_time = Date.parse(timeslot_params[:start_time])
end_time = Date.parse(timeslot_params[:end_time])
@timeslot = current_user.timeslots.build(timeslot_params)
@timeslot.price = experience.price
@timeslot.experience = experience
@timeslot.save
flash[:notice] = "Timeslot created successfully!"
redirect_back(fallback_location: request.referer, notice: "Timeslot created")
end
# PATCH/PUT /experiences/1
# PATCH/PUT /experiences/1.json
def update
experience = Experience.find(params[:experience_id])
@timeslot = Timeslot.find(params[:id])
new_params = timeslot_params
new_params = timeslot_params.merge
if @timeslot.update(new_params)
flash[:notice] = "Updated..."
else
flash[:notice] = "Something went wrong..."
end
redirect_back(fallback_location: request.referer)
end
def edit
end
def reservations
end
private
def timeslot_params
params.require(:timeslot).permit(:inventory, :price, :start_time, :end_time)
end
def set_timeslot
@timeslot = Timeslot.find(params[:id])
end
end
host.html.erb
<% if !@experiences.blank? %>
<div class="container">
<div class="row">
<div class="col-md-6">
<h2>Your Timeslot Manager</h2>
<p>This is your host calendar where you can add timeslots.</p>
<%= link_to "Back to Dashboard", hosting_dashboard_path, class: "btn btn-geoguides-o" %>
</div>
<%= search_form_for @search, class: "form-group", url: host_calendar_path do |f| %>
<div class="col-md-12 select" style="top: 25px;">
<div class="form-group">
<label>Your Experiences</label>
<%= f.select :experience_id, options_for_select(@experiences.collect {|u| [u.name, u.id] if u.published?}.compact, params[:experience_id]), {}, {
onchange: "$(this.form).submit()",
class: "form-control"
} %>
</div>
</div>
<%= f.hidden_field :start_time, id: "start_time", value: params[:start_time], onchange: "$(this.form).submit()" %>
<% end %>
</div>
<%= render 'form' %>
<%= render 'editform' %>
<% end %>
</div>
<hr/><br/>
<div class="container">
<div id="calendar">
</div>
</div>
<script>
window.timeslots = <%= raw @events.to_json %>
console.log(timeslots);
function showTimeslots(data) {
return data.map(function (e) {
return {
name: e.fullname,
inventory: e.inventory,
timeslot: e.id,
price: e.price,
start_time: e.start_time,
end_time: e.end_time,
start: e['start_time'],
end: e['end_time']
}
})
}
$('#calendar').fullCalendar({
header: {
left: 'title',
center: '',
right: 'month,agendaWeek,agendaDay,prev,next'
},
defaultDate: $('#start-time').val(),
editable: true,
events: showTimeslots(timeslots),
eventClick: function(event){
if (event.url) {
window.open(event.url);
return false;
}
console.log(event.timeslot);
console.log(event.start_time);
console.log(event.end_time);
var experience = '<%= j @experience.id.to_s %>';
console.log(experience);
$('#timeslot_id').val(event.timeslot);
$('#edit_calendar').modal('show');
$("#edit_timeslot").attr("action", "/experiences/" + experience + "/timeslots/" + event.timeslot);
var start = moment(event.start_time).tz('UTC').format('YYYY-MM-DD hh:mm a');
var end = moment(event.end_time).tz('UTC').format('YYYY-MM-DD hh:mm a');
console.log(start);
$('#timeslot_edit_start_time').datetimepicker({
dateFormat: 'yy-mm-dd',
setDate: start,
controlType: 'select',
oneLine: true,
timeFormat: 'hh:mm tt',
showTimezone: false,
timezoneList: [
{ value: 0, label: 'UTC'}
]
});
$('#timeslot_edit_end_time').datetimepicker({
dateFormat: 'yy-mm-dd',
setDate: end,
controlType: 'select',
oneLine: true,
timeFormat: 'hh:mm tt',
showTimezone: false,
timezoneList: [
{ value: 0, label: 'UTC'}
]
});
$('#timeslot_edit_start_time').val(moment(event.start_time).tz('UTC').format('YYYY-MM-DD hh:mm a'));
$('#timeslot_edit_end_time').val(moment(event.end_time).tz('UTC').format('YYYY-MM-DD hh:mm a'));
$('#timeslot_edit_inventory').val(event.inventory);
$('#timeslot_edit_price').val(event.price);
},
eventRender: function(event, element, view) {
var eventsdate = new Date(event.start_time);
var eventedate = new Date(event.end_time);
var e_start_time = moment(eventsdate);
var e_end_time = moment(eventedate);
var userTZ = moment.tz.guess();
console.log(moment(event.start_time).tz('UTC').format('h:mm A Z'));
var e_S_Clean = moment(event.start_time).tz('UTC').format('h:mm A');
var e_E_Clean = moment(event.end_time).tz('UTC').format('h:mm A');
return $(`
<a class="fc-day-grid-event fc-h-event fc-event fc-start fc-end">
<div class="fc-content">
<span class="fc-title">
<span>${e_S_Clean} - ${e_E_Clean} </span><br/>
Spaces: ${event.inventory} | Price: $${event.price}
<span/>
<div/>
<a/>
`);
},
/*dayRender: function(date, cell){
<% if !@experiences.blank? %>
cell.append('<span class="day-price">' + '$<%= @experience.price %>' + '</span>')
<% end %>
},*/
selectable: true,
selectHelper: true,
select: function(start, end, jsEvent, view) {
<% if @experiences.blank? %>
$('#calendar').fullCalendar('unselect');
<% end %>
$('#new_calendar').modal('show');
var start_date = moment(start);
var end_date = moment(end).subtract(1, "days");
$('#timeslot_start_time').datetimepicker({
dateFormat: 'yy-mm-dd',
setDate: start_date.format("yy-mm-dd hh:mm"),
controlType: 'select',
oneLine: true,
timeFormat: 'hh:mm tt',
showTimezone: false,
timezoneList: [
{ value: 0, label: 'UTC'}
]
});
$('#timeslot_end_time').datetimepicker({
dateFormat: 'yy-mm-dd',
setDate: end_date.format("yy-mm-dd hh:mm"),
controlType: 'select',
oneLine: true,
timeFormat: 'hh:mm tt',
showTimezone: false,
timezoneList: [
{ value: 0, label: 'UTC'}
]
});
$('#timeslot_start_time').val(start_date.format("YYYY-MM-DD hh:mm a"));
$('#timeslot_end_time').val(end_date.format("YYYY-MM-DD hh:mm a"));
}
});
$('.fc-prev-button').click(function(){
var current = new Date($('#start-time').val());
var prev = new Date(current.getFullYear(), current.getMonth() - 1, 1)
$('#start-time').val(moment(prev).format('YYYY-MM-DD'))
$('#start-time').trigger('change')
});
$('.fc-next-button').click(function(){
var current = new Date($('#start-time').val());
var next = new Date(current.getFullYear(), current.getMonth() + 1, 1)
$('#start-time').val(moment(next).format('YYYY-MM-DD'))
$('#start-time').trigger('change')
});
</script>
_editform.html.erb
<div class="modal fade" id="edit_calendar">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<form class="edit_timeslot" id="edit_timeslot" action="" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="_method" value="patch"><input type="hidden" name="authenticity_token" value="f2j0yxOJBXZQ78egS5ZbKHuepV2L2+S6U37TfRdvFVh3FD/vIEgdfNZTtuT/sfrr5QAXCRnhdUoZwD+0daBKFg==">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input readonly="readonly" value="2018-04-01" class="form-control datetimepicker hasDatepicker" style="cursor: pointer;" type="text" name="timeslot[start_time]" id="timeslot_edit_start_time">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input readonly="readonly" value="2018-04-01" class="form-control datetimepicker hasDatepicker" style="cursor: pointer;" type="text" name="timeslot[end_time]" id="timeslot_edit_end_time">
</div>
</div>
</div>
<div class="row">
<div class="col-md-10">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">#</span>
<input placeholder="How many people can come?" class="form-control" required="required" type="text" name="timeslot[inventory]" id="timeslot_edit_inventory">
</div>
</div>
</div>
<div class="col-md-2">
<p style="margin-top: 10px">Inventory</p>
</div>
</div>
<div class="row new-pricing">
<div class="col-md-10">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">$</span>
<input class="form-control" value="120" required="required" type="text" name="timeslot[price]" id="timeslot_edit_price">
</div>
</div>
</div>
<div class="col-md-2">
<p style="margin-top: 10px">Per Booking</p>
</div>
</div>
<div class="no-pricing hide">
</div>
<div class="form-group">
<button name="button" type="submit" class="btn btn-success">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
$('#datetimepicker').datetimepicker({
icons: {
time: "fa fa-clock-o",
date: "fa fa-calendar",
up: "fa fa-chevron-up",
down: "fa fa-chevron-down",
previous: 'fa fa-chevron-left',
next: 'fa fa-chevron-right',
today: 'fa fa-screenshot',
clear: 'fa fa-trash',
close: 'fa fa-remove'
}
});
$(function() {
var notAvailable = $('#calendar_status_not_available'),
available = $('#calendar_status_available');
notAvailable.click(function() {
$('.no-pricing').show();
$('.new-pricing').hide();
});
available.click(function() {
$('.no-pricing').hide();
$('.new-pricing').show();
});
});
</script>
<script>
$('#datetimepicker').datetimepicker({
icons: {
time: "fa fa-clock-o",
date: "fa fa-calendar",
up: "fa fa-chevron-up",
down: "fa fa-chevron-down",
previous: 'fa fa-chevron-left',
next: 'fa fa-chevron-right',
today: 'fa fa-screenshot',
clear: 'fa fa-trash',
close: 'fa fa-remove'
}
});
$(function() {
var notAvailable = $('#calendar_status_not_available'),
available = $('#calendar_status_available');
notAvailable.click(function() {
$('.no-pricing').show();
$('.new-pricing').hide();
});
available.click(function() {
$('.no-pricing').hide();
$('.new-pricing').show();
});
});
</script>