How can I bind an array object to FullCalendar events? - javascript

Vue.component('full-calendar', {
template: '<div ref="calendar"></div>',
props: {
tasks: {
type: Array,
required: true
},
newtask: Object
},
watch: {
tasks: function (task) {
// this.tasks.push(task);
// this.cal.calendar.addEvent({
// title: task.title,
// start: task.start,
// end: task.end
// });
$("#addTaskModal").modal('hide');
}},
data () {
return {
cal: null
}
},
methods: {
init:function(){
var self = this;
self.cal = $(self.$refs.calendar);
var args = {
firstDay: 1,
lang: 'en',
header: {
left: 'prev,next today',
center: 'title',
right: 'addTaskButton / dayGridMonth,timeGridWeek,listMonth'
},
height: "auto",
allDaySlot: false,
slotEventOverlap: false,
timeFormat: 'HH:mm',
plugins: ["interaction", "dayGrid"],
eventLimit: true,
events: this.tasks,
dateClick: function(date)
{
self.$emit('date_clicked', date);
console.log('date clicked');
console.log(this);
},
eventClick: function(event)
{
self.$emit('event_clicked', event);
},
customButtons: {
addTaskButton: {
text: 'Add Task',
click: function() {
$("#addTaskModal").modal('show');
}
}
}
}
if (self.editable)
{
args.editable = true;
args.eventResize = function(event)
{
self.$emit('event::resized', event);
}
args.eventDrop = function(event)
{
self.$emit('event::dropped', event);
}
}
if (self.droppable)
{
args.droppable = true;
args.eventReceive = function(event)
{
self.$emit('event::received', event);
}
}
self.cal.calendar = new FullCalendar.Calendar(self.$el,args);
self.cal.calendar.render();
}
},
mounted () {
this.init();
}
})
let vm = new Vue({
el: '#app',
data () {
return {
tasks: [
{
title: 'Event1',
start: '2019-05-10 12:30:00',
end: '2019-05-10 16:30:00'
},
{
title: 'Event2',
start: '2019-05-07 17:30:00',
end: '2019-05-07 21:30:00'
}
],
editable: false,
selectedDate : moment().format('DD-MM-YYYY'),
task: {
title:null,
start: '2019-05-07 17:30:00',
end: '2019-05-07 21:30:00'
},
newtask: {}
}
},
methods: {
addTask: function(event){
var d = moment().format('YYYY-MM-DD');
var sel = new Date(this.selectedDate.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3"));
//console.log();
var date = new Date(moment(sel).format('YYYY-MM-DD')+ 'T00:00:00'); // will be in local time
this.tasks.push({
title: this.task.title,
start: date,
end: date
});
this.$nextTick(function () {
// DOM is now updated
// `this` is bound to the current instance
//this.doSomethingElse()
})
},
dateClicked: function(date) {
this.selectedDate = moment(date.date).format('DD-MM-YYYY');
},
eventClicked: function(event) {
this.selectedDate = moment(event.event.start).format('DD-MM-YYYY');
},
showObject: function() {
console.log(this.tasks);
}
}
})
<link href="https://fullcalendar.io/releases/core/4.1.0/main.min.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script src="https://fullcalendar.io/releases/core/4.1.0/main.min.js"></script>
<script src="https://fullcalendar.io/releases/daygrid/4.1.0/main.min.js"></script>
<script src="https://fullcalendar.io/releases/interaction/4.1.0/main.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<div class="container mt-5" id="app">
<div>
<div class="row">
<div class="col-md-8">
<full-calendar
v-bind:tasks="tasks"
v-on:date_clicked="dateClicked"
v-on:event_clicked="eventClicked"
:newtask="newtask"
></full-calendar>
</div>
<div class="col-md-4">
<div class="pb-3">
<span id="CurrentDate" class="" style="cursor: pointer;">{{selectedDate}}</span>
<span class="badge badge-primary">{{tasks.length}}</span>
<button #click="showObject">show object</button>
</div>
<table class="table table-condensed">
<tbody v-for="task in tasks">
<tr>
<td>
<input
type="checkbox"
/>
</td>
<td>{{task.title}}</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr v-if="tasks.length==0">
<td colspan="3" class="text-center">No tasks to display</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="addTaskModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add a task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" id="NewTaskTitle" placeholder="Enter task name" class="form-control" v-model="task.title" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success btn-sm" #click="addTask">Add</button>
<button data-bind="click: CancelAddNewTask" class="btn btn-seconday btn-sm" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>
Hi everyone,
I am trying to bind an object ‘tasks’ with full calendar events however it is not working.
Please see example above provided. View it in full page please
When you add a task, I am expecting it to be added to the tasks objects and of course to be be binded to the events in full calendar.
Basically, I want to bind tasks array to full calendar events object, so if for example I remove an item should also be removed from the full calendar events
Please let me know if I am doing it wrong . thanks a bunch
[1]:

It should be as simple as updating the FullCalendar when new tasks are sent from the Parent (new Vue) to Child (full-calendar).
In your full-calendar component you should be able to just call the render() method which according to the FullCalendar docs will rerender the calendar if it already exists. In your architecture it is as simple as recalling the init() method. I also moved close modal logic to the appropriate place. This could probably user a bit more refactoriing but this should get you unstuck. Hope it helps.
watch: {
tasks: function (task) {
this.cal.calendar.render();
}
}
https://fullcalendar.io/docs/render
Vue.component('full-calendar', {
template: '<div ref="calendar"></div>',
props: {
tasks: {
type: Array,
required: true
},
newtask: Object
},
watch: {
tasks: function (task) {
this.init()
}
},
data () {
return {
cal: null
}
},
methods: {
init:function(){
var self = this;
self.cal = $(self.$refs.calendar);
var args = {
firstDay: 1,
lang: 'en',
header: {
left: 'prev,next today',
center: 'title',
right: 'addTaskButton / dayGridMonth,timeGridWeek,listMonth'
},
height: "auto",
allDaySlot: false,
slotEventOverlap: false,
timeFormat: 'HH:mm',
plugins: ["interaction", "dayGrid"],
eventLimit: true,
events: this.tasks,
dateClick: function(date)
{
self.$emit('date_clicked', date);
console.log('date clicked');
console.log(this);
},
eventClick: function(event)
{
self.$emit('event_clicked', event);
},
customButtons: {
addTaskButton: {
text: 'Add Task',
click: function() {
$("#addTaskModal").modal('show');
}
}
}
}
if (self.editable)
{
args.editable = true;
args.eventResize = function(event)
{
self.$emit('event::resized', event);
}
args.eventDrop = function(event)
{
self.$emit('event::dropped', event);
}
}
if (self.droppable)
{
args.droppable = true;
args.eventReceive = function(event)
{
self.$emit('event::received', event);
}
}
self.cal.calendar = new FullCalendar.Calendar(self.$el,args);
self.cal.calendar.render();
}
},
mounted () {
this.init();
}
})
let vm = new Vue({
el: '#app',
data () {
return {
tasks: [
{
title: 'Event1',
start: '2019-05-10 12:30:00',
end: '2019-05-10 16:30:00'
},
{
title: 'Event2',
start: '2019-05-07 17:30:00',
end: '2019-05-07 21:30:00'
}
],
editable: false,
selectedDate : moment().format('DD-MM-YYYY'),
task: {
title:null,
start: '2019-05-07 17:30:00',
end: '2019-05-07 21:30:00'
},
newtask: {}
}
},
methods: {
addTask: function(event){
var d = moment().format('YYYY-MM-DD');
var sel = new Date(this.selectedDate.replace( /(\d{2})-(\d{2})-(\d{4})/, "$2/$1/$3"));
//console.log();
var date = new Date(moment(sel).format('YYYY-MM-DD')+ 'T00:00:00'); // will be in local time
this.tasks.push({
title: this.task.title,
start: date,
end: date
});
$("#addTaskModal").modal('hide');
this.$nextTick(function () {
// DOM is now updated
// `this` is bound to the current instance
//this.doSomethingElse()
})
},
dateClicked: function(date) {
this.selectedDate = moment(date.date).format('DD-MM-YYYY');
},
eventClicked: function(event) {
this.selectedDate = moment(event.event.start).format('DD-MM-YYYY');
},
showObject: function() {
console.log(this.tasks);
}
}
})
<link href="https://fullcalendar.io/releases/core/4.1.0/main.min.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script src="https://fullcalendar.io/releases/core/4.1.0/main.min.js"></script>
<script src="https://fullcalendar.io/releases/daygrid/4.1.0/main.min.js"></script>
<script src="https://fullcalendar.io/releases/interaction/4.1.0/main.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<div class="container mt-5" id="app">
<div>
<div class="row">
<div class="col-md-8">
<full-calendar
v-bind:tasks="tasks"
v-on:date_clicked="dateClicked"
v-on:event_clicked="eventClicked"
:newtask="newtask"
></full-calendar>
</div>
<div class="col-md-4">
<div class="pb-3">
<span id="CurrentDate" class="" style="cursor: pointer;">{{selectedDate}}</span>
<span class="badge badge-primary">{{tasks.length}}</span>
<button #click="showObject">show object</button>
</div>
<table class="table table-condensed">
<tbody v-for="task in tasks">
<tr>
<td>
<input
type="checkbox"
/>
</td>
<td>{{task.title}}</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr v-if="tasks.length==0">
<td colspan="3" class="text-center">No tasks to display</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="addTaskModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add a task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" id="NewTaskTitle" placeholder="Enter task name" class="form-control" v-model="task.title" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success btn-sm" #click="addTask">Add</button>
<button data-bind="click: CancelAddNewTask" class="btn btn-seconday btn-sm" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>

watch: {
tasks: function (tasks) {
this.calendarOptions.events = tasks;
let calendarApi = this.$refs.fullcalendar.getApi();
calendarApi.render();
},
},
... ...
<FullCalendar
ref="fullcalendar"
:options="calendarOptions"
/>

Related

How can I add bootstrap 'modal' in fullCalander

Hi I'm making fullCalendar page for giving information of some events.
When I click any date or event, my goal is give specific information.
So I want to add bootstrap's component 'modal' in fullCalendar.
I searched much time.. but I couldn't get solution for my problem.
How can I add modal on my fullCalendar page well.. Please help me.
My codes
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
timeZone: 'UTC',
initialView: 'dayGridMonth',
height: '800px',
events:[
{
title: "'event1",
color : "yellow",
textColor : "black",
start: '2022-06-01 00:00:00',
end: '2022-08-31 24:00:00'
},
{
title: 'event2',
start: '2022-08-17',
end: '2022-08-21'
},
{
title: 'event3',
start: '2022-08-17',
end: '2022-08-21'
},
{
title: 'event4',
start: '2022-08-31',
end: '2022-09-05'
},
{
title: 'event5',
start: '2022-08-26',
color : "lightblue",
textColor : "black",
end: '2022-09-03'
}
],
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
editable: false,
displayEventTime: false
});
calendar.render();
});
</script>
<body>
<div id="calendarBox">
<div id="calendar"></div>
</div>
</body>
</html>
Thank you all for reading my long question.
You can user eventClick option for click event of any of the event.
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
timeZone: 'UTC',
initialView: 'dayGridMonth',
height: '800px',
eventClick: function(info) {
var eventObj = info.event;
console.log(eventObj);
if (eventObj.start) {
//alert('Clicked on ' + eventObj.start);
$('#calender_event').modal('show');
$('.modal-title').html(eventObj.title);
}
},
events:[
{
title: "'event1",
color : "yellow",
textColor : "black",
start: '2022-06-01 00:00:00',
end: '2022-08-31 24:00:00'
},
{
title: 'event2',
start: '2022-08-17',
end: '2022-08-21'
},
{
title: 'event3',
start: '2022-08-17',
end: '2022-08-21'
},
{
title: 'event4',
start: '2022-08-31',
end: '2022-09-05'
},
{
title: 'event5',
start: '2022-08-26',
color : "lightblue",
textColor : "black",
end: '2022-09-03'
}
],
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
editable: false,
displayEventTime: false
});
calendar.render();
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar#5.3.1/main.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar#5.3.1/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/js/bootstrap.bundle.min.js" ></script>
<div id="calendarBox">
<div id="calendar"></div>
</div>
<!-- Modal -->
<div class="modal fade" id="calender_event" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Here will be the body of popup (You can populate it dynamically as well)...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

Infinite loop VueJS API calls

I got infinite api calls when this method setCurrentDateFilter called after clicking on radio button. It looks like my filtered list rerenders every time because of reactivity. But actually i don't understand the reason why. Everything was fine before i did this additional api call on button click.
index.html partially
<div class="row align-items-center justify-content-center">
<b-form-group>
<b-form-radio-group buttons v-model="selected_date" :change="setCurrentDateFilter()" name="date_filter">
<b-form-radio value="today" button-variant="outline-success">Сегодня</b-form-radio>
<b-form-radio value="tomorrow" button-variant="outline-success">Завтра</b-form-radio>
<!-- <b-form-radio value="specific" button-variant="outline-success" disabled>Выбрать дату</b-form-radio> -->
</b-form-radio-group>
</b-form-group>
</div>
<div class="container">
<div class="section-top-border" v-for="(event, i) in filteredEvents" :key="event.id">
<div class="row">
<div class="col-md-6">
<div class="country">
<div class="grid">
<div class="row">
<div class="col-sm-3 event date">{{event.start_date.day}}</div>
<div class="col-sm-6 event month">{{event.start_date.month}}</div>
</div>
<div class="row event">
<div class="col-sm-1">{{event.start_date.time}} </div>
<div class="col-sm-11" v-if="event.place"> 📌 {{event.place.name}} </div>
</div>
</div>
</div>
</div>
</div>
<h3 class="mb-30">{{event.title}}</h3>
<div class="row">
<div class="col-md-3">
<b-img v-bind:src="event.poster_link" alt="" width="200" height="200" fluid>
</div>
<div class="col-md-9 mt-sm-20">
<p>{{event.short_description}}</p>
<b-btn variant="outline-success" v-on:click="currentEvent=event;modalShow=true"> 👁 Подробнее</b-btn>
</div>
</div>
</div>
main.js
var app = new Vue({
el: '#app',
data: {
api: 'http://127.0.0.1:8000/api/events',
show: true,
events: [],
currentEvent: Object,
modalShow: false,
loading: true,
errored: false,
selected_filter: ["1", "2", "3"],
selected_date: "today",
},
computed: {
filteredEvents() {
var sel_filter = this.selected_filter
var objs = this.events.filter(function(event) {
return sel_filter.indexOf(event.type.id.toString()) >= 0
})
console.log(objs.length, sel_filter)
return objs;
}
},
mounted() {
this.getEventsFromServer();
},
methods: {
getEventsFromServer(date = (new Date).toString()) {
axios
.get(this.api)
.then(response => {
this.events = handleResponse(response)
})
.catch(error => {
console.log(error);
this.errored = true;
})
.finally(() => (this.loading = false));
},
setCurrentDateFilter: function(e) {
console.log(e)
console.log(this.selected_date)
this.getEventsFromServer();
},
},
filters: {}
})
function handleResponse(response) {
var events = []
for (let i = 0; i < response.data.length; i++) {
let e = response.data[i]
let start_date = new Date(e.start_date)
let el = {
start_date: {
day: start_date.getDate(),
time: start_date.getHours() + ":" + (start_date.getMinutes() < 10 ? '0' : '') + start_date.getMinutes(),
month: getMonthWord(start_date)
},
title: e.id,
title: e.title,
description: e.description,
short_description: e.short_description,
poster_link: e.poster_link,
source_link: e.source_link,
type: getStyledType(e.type),
phone: e.phone,
email: e.email,
place: e.place
}
events.push(el)
}
return events;
}

Validation error message doesn't appear for custom DatePicker Angular Formly field

I'm trying to use Angular Datetime Picker as a Angular Formly input type. I've got it working such that I can edit and set a value that is correctly added to the binded model.
However, I can't get the validation error messages to display like on the regular input fields.
JS Bin with what I've got so far. As you can see the red color doesn't appear when you exit the field, only when you try to submit. And the error message never shows up.
Formly Config:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
Fields
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
Templates
<script type="text/ng-template" id="custom-template.html">
<div class="form-group">
<label class="control-label" for="{{::id}}">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model[options.key]"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
</script>
After investigating this deeper, I can see the control you used Angular Datetime Picker is not fully compatible with Angular Formly.
This is because of the reason that it's overwriting the AngularJS's
ngModelController.$render() method and hence not setting the value
for $touched like other input controls.
Another reason in your code is, the config and the template
error-messages.html are treating the custom control as single
element with fc.$touched, fc.$error and fc.$viewValue whereas
DatePicker is rendering as group of elements (array).
To get rid of all these issues, you can have a custom directive to set $touched as below,
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
And in custom-template.html,
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
And add fc[0].$touched in below configuration to take care of array of fields,
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
And also add below section in error-messages.html to take care of array of fields,
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
This changes will fix the issue.
As you can see a bit of design issue with the error message which is displayed further down,
You can change the custom-template.html as below by removing the div wrapper <div class="form-group">,
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
I have updated your JSBin with these changes.
Snippet:
/* global angular */
(function() {
'use strict';
var app = angular.module('formlyExample', ['formly', 'formlyBootstrap', 'ngAnimate', 'ngMessages', 'ui.bootstrap.datetimepicker', 'ui.dateTimeInput'], function config(formlyConfigProvider) {
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
});
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
app.controller('MainCtrl', function MainCtrl(formlyVersion) {
var vm = this;
vm.onSubmit = onSubmit;
vm.model = {};
vm.options = {};
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'moretext',
type: 'input',
templateOptions: {
label: 'More Text',
placeholder: 'Write something else',
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
if (vm.form.$valid) {
vm.options.updateInitialValue();
alert(JSON.stringify(vm.model), null, 2);
}
}
});
})();
body {
margin: 20px
}
.formly-field {
margin-bottom: 30px;
}
.error-messages {
position: relative;
}
.error-messages, .message {
opacity: 1;
transition: .3s linear all;
}
.message {
font-size: .8em;
position: absolute;
width: 100%;
color: #a94442;
margin-top: 4px;
}
.error-messages.ng-enter.ng-enter-active,
.message.ng-enter.ng-enter-active {
opacity: 1;
top: 0;
}
.error-messages.ng-enter,
.message.ng-enter {
opacity: 0;
top: -10px;
}
.error-messages.ng-leave,
.message.ng-leave {
opacity: 1;
top: 0;
}
.error-messages.ng-leave-active,
.message.ng-leave-active {
opacity: 0;
top: -10px;
}
<!DOCTYPE html>
<html>
<head>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<!-- Twitter bootstrap -->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- apiCheck is used by formly to validate its api -->
<script src="//npmcdn.com/api-check#latest/dist/api-check.js"></script>
<!-- This is the latest version of angular (at the time this template was created) -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<!-- This is the latest version of formly core. -->
<script src="//npmcdn.com/angular-formly#latest/dist/formly.js"></script>
<!-- This is the latest version of formly bootstrap templates -->
<script src="//npmcdn.com/angular-formly-templates-bootstrap#latest/dist/angular-formly-templates-bootstrap.js"></script>
<script src="https://rawgit.com/angular/bower-angular-messages/v1.4.4/angular-messages.js"></script>
<script src="https://rawgit.com/angular/bower-angular-animate/v1.4.4/angular-animate.js"></script>
<!-- Moment -->
<script src="https://cdn.rawgit.com/moment/moment/develop/min/moment-with-locales.min.js"></script>
<!-- Datetime picker -->
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.templates.js"></script>
<link href="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/css/datetimepicker.css" rel="stylesheet">
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-date-time-input/master/src/dateTimeInput.js"></script>
<title>Angular Formly Example</title>
</head>
<body ng-app="formlyExample" ng-controller="MainCtrl as vm">
<div>
<form ng-submit="vm.onSubmit()" name="vm.form" novalidate>
<formly-form model="vm.model" fields="vm.fields" options="vm.options" form="vm.form">
<button type="submit" class="btn btn-primary submit-button">Submit</button>
<button type="button" class="btn btn-default" ng-click="vm.options.resetModel()">Reset</button>
</formly-form>
</form>
<hr />
<h2>Model</h2>
<pre>{{vm.model | json}}</pre>
<h2>Fields <small>(note, functions are not shown)</small></h2>
<pre>{{vm.originalFields | json}}</pre>
<h2>Form</h2>
<pre>{{vm.form | json}}</pre>
</div>
<!-- Put custom templates here -->
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
</script>
</body>
</html>
You should return your validation in the formlyConfigProvider without passing it as the value for templateOptions. Return
validation: {
show: true
}
instead of
templateOptions: {
validation: {
show: true
}
}
Your formlyConfigProvider should look something like this:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
validation: {
show: true
}
};
}
});
Here is the JSBin for the working code.

Full Calendar with Modal and Multiple event details - Meteor

I'm using the FullCalendar package as well as the below code which is working perfectly:
HTML:
<body>
{{>calendar}}
</body>
</template>
<template name="calendar">
{{#if showEditEvent}}
{{>editEvent}}
{{/if}}
<div class="container">
<div class="row">
<div class="col-md-2">
</div>
<div class="col-md-8">
<div id="calendar">
</div>
</div>
<div class="col-md-2">
</div>
</div>
</div>
</template>
<template name="editEvent">
<!--Modal Dialog-->
<div class="modal" id="EditEventModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria- hidden="true">x</button>
<h4 class="modal-title">Agenda Item</h4>
</div>
<div class="modal-body">
<label for="title">Item: </label><input type="text" class="title" name="title" value="{{evt.title}}" id="title">
</div>
<div class="modal-footer">
Delete
Save
Cancel
</div>
</div>
</div>
</div>
JS:
// Set session defaults
Session.setDefault('editing_calevent', null);
Session.setDefault('showEditEvent', false);
Template.calendar.showEditEvent = function(){
return Session.get('showEditEvent');
}
Template.editEvent.evt = function(){
// run a query to the database
var calEvent = CalEvents.findOne({_id:Session.get('editing_calevent')});
return calEvent;
}
var updateCalendar = function(){
$('#calendar').fullCalendar( 'refetchEvents' );
}
Template.editEvent.events({
'click .save':function(evt,tmpl)
{updateCalEvent(Session.get('editing_calevent'),tmpl.find('.title').value);
Session.set('editing_calevent',null);
Session.set('showEditEvent',false);
},
'click .close':function(evt,tmpl){
Session.set('editing_calevent',null);
Session.set('showEditEvent',false);
$('#EditEventModal').modal("hide");
} ,
'click .remove':function(evt,tmpl){
removeCalEvent(Session.get('editing_calevent'));
Session.set('editing_calevent',null);
Session.set('showEditEvent',false);
$('#EditEventModal').modal("hide");
}
})
Template.calendar.rendered = function(){
$('#calendar').fullCalendar({
header:{
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
// Event triggered when someone clicks on a day in the calendar
dayClick:function( date, allDay, jsEvent, view) {
// Insert the day someone's clicked on
CalEvents.insert({title:'New Item',start:date,end:date});
// Refreshes the calendar
updateCalendar();
},
eventClick:function(calEvent,jsEvent,view){
// Set the editing_calevent variable to equal the calEvent.id
Session.set('editing_calevent',calEvent.id);
// Set the showEditEvent variable to true
Session.set('showEditEvent', true);
$('#EditEventModal').modal("show");
},
eventDrop:function(calEvent){
CalEvents.update(calEvent.id,
{$set: {start:calEvent.start,end:calEvent.end}});
updateCalendar();
},
events: function(start, end, callback) {
// Create an empty array to store the events
var events = [];
// Variable to pass events to the calendar
// Gets us all of the calendar events and puts them in the array
calEvents = CalEvents.find();
// Do a for each loop and add what you find to events array
calEvents.forEach(function(evt){
events.push(
{ id:evt._id,title:evt.title,start:evt.start,end:evt.end});
})
// Callback to pass events back to the calendar
callback(events);
},
editable:true
});
}
var removeCalEvent = function(id,title){
CalEvents.remove({_id:id});
updateCalendar();
}
var updateCalEvent = function(id,title){
CalEvents.update(id, {$set: {title:title}});
updateCalendar();
}
My two part question is:
A) how do i integrate something like the below in order to have more than one custom fields in the JSON feed?
B) how do I store the resultant data in a new Mongo Collection?
$(document).ready(function() {
$('#bootstrapModalFullCalendar').fullCalendar({
events: '/hackyjson/cal/',
header: {
left: '',
center: 'prev title next',
right: ''
},
eventClick: function(event, jsEvent, view) {
$('#modalTitle').html(event.title);
$('#modalBody').html(event.description);
$('#eventUrl').attr('href',event.url);
$('#fullCalModal').modal();
}
});
});
Thank you.

jquery daterangepicker not working in modal

I have a modal popup (from bootstrap) that opens and contains a text input with daterangepicker, but the daterangepicker does not work (i see nothing when i click on the textbox) and i see no errors in the console.
Here is the input:
<div id="divChooseDossier" class="modal hide fade" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>#DossierReceipts.ChooseDossier</h3>
</div>
<div class="modal-body">
<input type="text" class="datePicker ui-rangepicker-input search-query input-small"
id="lastModifiedDateFilter" />
</div>
<div class="modal-footer">
#DossierReceipts.Cancel
</div>
Here is the javascript to create the daterangepicker:
$("#lastModifiedDateFilter").daterangepicker({
dateFormat: "yy.mm.dd"
, rangeSplitter: '-'
});
And here is the javascript to open the popup:
$("#divCreateReceipt").modal("show");
Does anyone know why does this not work?
Thanks
UPDATE
Here is the complete code for the popup window:
#{
ViewBag.Title = "Dosare";
}
#using ExpertExecutor.Resources.Dossier
#section leftMenu{
#Html.Partial("_LeftMenu")
}
#Scripts.Render("~/bundles/daterangepicker")
#Scripts.Render("~/bundles/watermark")
#Styles.Render("~/Content/daterangepicker")
<script src="#Url.Content("~/Scripts/jquery.watermark.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("/Scripts/jquery.jqGrid.fluid.js")"></script>
#Html.Hidden("redirectUrl", (string)ViewBag.RedirectUrl)
<div class="form-search form-inline alert alert-info">
<fieldset>
<legend>#Index.FiltersCaption</legend>
<dl>
<dd>
<span>#Index.DossierColumn</span>
<input type="text" id="dossierFilter" class="search-query input-xxlarge" />
</dd>
<dd>
<span>#Index.DossierStatusColumn</span>
#Html.DropDownList("dossierStatusFilter", (List<SelectListItem>)ViewData["DossierStatuses"], new { #class = "input-medium" })
<span>#Index.LastModifiedDateColumn</span>
<input type="text" class="datePicker ui-rangepicker-input search-query input-small"
id="lastModifiedDateFilter" />
<span>#Index.LastOperatorColumn</span>
#Html.DropDownList("lastOperatorFilter", (List<SelectListItem>)ViewData["Users"])
</dd>
<dd>
<input type="button" class="btn btn-info" value="#Index.Search" onclick="applyFilter();"/>
<input type="button" class="btn btn-info" value="#Index.ClearFilter" onclick="clearFilter();" />
</dd>
</dl>
</fieldset>
</div>
<div id="dossiersGridWrapper" class="row-fluid">
<table id="dossiersGrid"></table>
<div id="dossiersGridPager"></div>
</div>
#if (!ViewBag.NoActions)
{
#Index.CreateDossier
}
<script type="text/javascript">
$('#dossierFilter').watermark('#Index.WatermarkSearchDossier');
$.jgrid.defaults.loadtext = '#Index.GridLoading';
var mvcJqGrid = {
customDblClick: "#ViewBag.customDblClick",
actions: {
buttonize: function (cellvalue, options, rowobject) {
return '<a onclick="return mvcJqGrid.actions.edit(\'' + options.rowId + '\')" href="#" title="Editare dosar"><i class="ui-icon ui-icon-pencil" style="display:inline-block"></i></a>' +
'<a onclick="return mvcJqGrid.actions.costs(\'' + options.rowId + '\')" href="#" title="Cheltuieli dosar"><i class="ui-icon ui-icon-cart" style="display:inline-block"></i></a>' +
'<a onclick="return mvcJqGrid.actions.imobil(\'' + options.rowId + '\')" href="#" title="Bunuri imobile"><i class="ui-icon ui-icon-home" style="display:inline-block"></i></a>' +
'<a onclick="return mvcJqGrid.actions.mobil(\'' + options.rowId + '\')" href="#" title="Bunuri mobile"><i class="ui-icon ui-icon-suitcase" style="display:inline-block"></i></a>' +
'<a onclick="return mvcJqGrid.actions.open(\'' + options.rowId + '\')" href="#" title="Open Dossier"><i class="ui-icon ui-icon-folder-open" style="display:inline-block"></i></a>';
},
edit: function (id) {
window.open('#Url.Action("EditDossier", "Dossier")?id=' + id, "_self");
return false;
},
costs: function (id) {
window.open('#Url.Action("OpenRedirect", "Dossier")?idDossier=' + id + '&strUrl=' + encodeURI('#Url.Action("DossierCosts", "Dossier")?id=' + id), "_self");
return false;
},
imobil: function (id) {
window.open('#Url.Action("OpenRedirect", "Dossier")?idDossier=' + id+'&strUrl='+encodeURI('#Url.Action("ImovableList", "Asset")?idDossier=' + id), "_self");
return false;
},
mobil: function (id) {
window.open('#Url.Action("OpenRedirect", "Dossier")?idDossier=' + id + '&strUrl=' + encodeURI('#Url.Action("MovableList", "Asset")?idDossier=' + id), "_self");
return false;
},
open: function (id) {
if (mvcJqGrid.customDblClick.length > 0 && typeof (window[mvcJqGrid.customDblClick]) == "function") {
return window[mvcJqGrid.customDblClick](id);
}
$.getJSON('#Url.Action("OpenDossier", "Dossier")' + "?id=" + id, function (data) {
if (data && data.success) {
var redirectUrl = $("#redirectUrl").val();
if (redirectUrl) {
window.open(redirectUrl, "_self");
} else {
window.location.reload();
}
} else {
alert("#Index.ErrorOpenDossier");
}
});
return false;
}
}
};
$("#dossiersGrid").jqGrid({
url: '#Url.Action("DossiersGridData", "Dossier")',
datatype: 'json',
mtype: 'POST',
colModel: [
{ name: "#Index.CompletedColumn", sortable: false, editable: false, index: "Completed" },
{ name: "#Index.DossierColumn", sortable: true, editable: false, index: "Dossier" },
{ name: "#Index.DossierStatusColumn", sortable: true, editable: false, index: "DossierStatus" },
{ name: "#Index.LastModifiedDateColumn", sortable: true, editable: false, index: "LastModifiedDate" },
{ name: "#Index.LastOperatorColumn", sortable: true, editable: false, index: "LastOperator" },
{ name: "#Index.CreditorsColumn", sortable: false, editable: false, index: "Creditors" },
{ name: "#Index.DebtorsColumn", sortable: false, editable: false, index: "Debtors" },
#if (!ViewBag.NoActions)
{
#:{ name: "#Index.Action", sortable: false, editable: false, index: "Action", formatter: mvcJqGrid.actions.buttonize }
}
],
viewrecords: true,
postData: {
dossierFilter: function () { return $("#dossierFilter").val(); },
dossierStatusFilter: function () { return $("#dossierStatusFilter").val(); },
lastModifiedDateFilter: function () { return $("#lastModifiedDateFilter").val(); },
lastOperatorFilter: function () {
return $("#lastOperatorFilter").val();
}
},
pager: "#dossiersGridPager",
rowNum: 10,
caption: "Lista dosare",
autowidth: true,
rowList: [10, 15, 20, 50],
emptyrecords: 'No record Found',
height: '100%',
ondblClickRow: mvcJqGrid.actions.open
});
$("#lastModifiedDateFilter").daterangepicker({
dateFormat: "yy.mm.dd"
, rangeSplitter: '-'
});
function applyFilter() {
$("#dossiersGrid").trigger("reloadGrid");
}
function clearFilter() {
$('#dossierFilter').val("");
$("#dossierStatusFilter").val("");
$("#lastModifiedDateFilter").val("");
$("#lastOperatorFilter").val("");
$("#dossiersGrid").trigger("reloadGrid");
}
if (leftMenu) {
leftMenu.setContext('dossier-list help-dossier');
}
var resizeDossiersGrid = function () {
$("#dossiersGrid").fluidGrid({ example: "#dossiersGridWrapper", offset: 0 });
};
$(window).on('resize', resizeDossiersGrid);
$("#dossiersGrid").on("jqGridGridComplete", resizeDossiersGrid);
</script>
And here is the complete code for the calling page:
#using ExpertExecutor.DataLayer.Models
#using ExpertExecutor.Resources.Cost
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section leftMenu{
#Html.Partial("_LeftMenu")
}
#section head
{
#Scripts.Render("~/bundles/jqueryval")
<style type="text/css">
#divChooseDossier {
width: 900px;
}
#divCreateReceipt {
width: 900px;
}
</style>
}
<h2>#ViewBag.Title</h2>
#Html.Hidden("IdDossier", ViewData["IdDossier"])
<table id="dossierReceiptsGrid"></table>
<div id="divCreateReceipt" class="modal hide fade" role="dialog" aria-hidden="true">
</div>
#DossierReceipts.CreateReceipt
<div id="divConfirmDossier" class="modal hide fade" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>#DossierReceipts.ConfirmDossier</h3>
</div>
<div class="modal-body">
<span>#DossierReceipts.ConfirmDossierMessage<strong>#(ViewData["Dossier"] != null ? string.Format("{0}/{1}", ((Dossier)ViewData["Dossier"]).DossierNumber, ((Dossier)ViewData["Dossier"]).DossierYear) : string.Empty)</strong>?</span>
</div>
<div class="modal-footer">
#DossierReceipts.Cancel
<input type="button" class="btn btn-primary" value="#DossierReceipts.ConfirmDossierOk" onclick="confirmDossier();"/>
<input type="button" class="btn" value="#DossierReceipts.SelectDossier" onclick="showChooseDossierModal();"/>
</div>
</div>
<div id="divChooseDossier" class="modal hide fade" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>#DossierReceipts.ChooseDossier</h3>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
#DossierReceipts.Cancel
</div>
</div>
<script type="text/javascript">
leftMenu.setContext('financial help-financial');
$("#dossierReceiptsGrid").jqGrid({
url: '#Url.Action("ReceiptsGridData")',
datatype: "json",
mtype: "POST",
postData: {
idDossier: '#ViewData["IdDossier"]'
},
colNames: ['#DossierReceipts.DossierColumn', '#DossierReceipts.ReceiptDateColumn', '#DossierReceipts.ReceiptValueColumn', '#DossierReceipts.ReceiptCurrencyColumn', '#DossierReceipts.ReceiptColumn'],
colModel: [
{ name: "Dossier", index: "Dossier", sortable: true, editable: false },
{ name: "ReceiptDate", index: "ReceiptDate", sortable: true, editable: false },
{ name: "ReceiptValue", index: "ReceiptValue", sortable: true, editable: false },
{ name: "Currency", index: "Currency", sortable: true, editable: false },
{ name: "Receipt", index: "Receipt", sortable: true, editable: false }
],
viewrecords: true
});
function confirmDossier() {
$("#divConfirmDossier").modal("hide");
$("#divCreateReceipt").modal("show");
}
var reloadDossiersGrid = true;
function showChooseDossierModal() {
$("#divConfirmDossier").modal("hide");
$("#divChooseDossier").modal("show");
if (reloadDossiersGrid) {
reloadDossiersGrid = false;
$.post('#Url.Action("Index", "Dossier")?redirectUrl=&noActions=true&partial=true&customDblClick=chooseDossier', null, function(postResponse) {
$("#divChooseDossier .modal-body").html(postResponse);
$("#divChooseDossier").on("shown", function() {
resizeDossiersGrid();
$("#lastModifiedDateFilter").daterangepicker({
dateFormat: "yy.mm.dd"
, rangeSplitter: '-'
});
});
});
} else {
$("#divChooseDossier").modal("show");
}
}
function chooseDossier(id) {
$("#IdDossier").val(id);
$("#divChooseDossier").modal("hide");
$.get('#Url.Action("CreateReceipt", "Financial")?idDossier=' + id, null, function(getResponse) {
$("#divCreateReceipt").html(getResponse);
$("#divCreateReceipt").modal("show");
});
$.get('#Url.Action("GetDossierDisplayName")?id=' + id, null, function(getResponse) {
$("#divConfirmDossier .modal-body strong").text(getResponse.name);
});
$("#IdDossier").val(id);
}
$(function() {
$("a[href='#divCreateReceipt']").hide();
$("a[href='#divChooseDossier']").hide();
});
function showCreateReceiptOption() {
if ($("#IdDossier").val() && $("#IdDossier").val().length > 0) {
$("#divConfirmDossier").modal("show");
} else {
showChooseDossierModal();
}
}
</script>
Sorry for the long code
Rather than modifying the z-index of elements, you can also set the parentEl option (where the calendar control is created). This will allow the actual daterangepicker object to inherit the z-index of the modal container.
$("#lastModifiedDateFilter").daterangepicker({
parentEl: "#divChooseDossier .modal-body"
})
From the documentation:
parentEl: (string) jQuery selector of the parent element that the date
range picker will be added to, if not provided this will be 'body'
I had a similar problem with datepicker jquery.
When I clicked on the input, nothing happened, no error, nothing.
The problem was that the datepicker was working, but the calendar appeared under the modal, I hacked this with css :
.datepicker{
z-index: 1100 !important;
}
Maybe your problem is similar to the mine ,
Update after 8 years of service....
Look at the better answer at bottom of this answer
You can change z-index in event show.daterangepicker
$('.daterange-single').on('show.daterangepicker', function(e){
var modalZindex = $(e.target).closest('.modal').css('z-index');
$('.daterangepicker').css('z-index', modalZindex+1);
});
I resolve my issues with the couple of :
.datepicker{
z-index: 1100 !important;
}
#ui-datepicker-div {
width: 30% !important;
}
Simply remove tabindex="-1" from your Bootstrap modal.
<div class="modal" tabindex="-1">
On version 0.21.1, insert the below CSS code to effect.
.date-picker-wrapper{
z-index: 1100 !important;
}

Categories