Okay so here's the story:
I have two buttons with two different controllers(handlers) - A plus and a minus button:
[ + ] addBtn [ - ] subtractBtn - hidden
The first time you click the addBtn, the subtractBtn should show.
The max amount of clicks for either button is 2.
When you click the addBtn, the count of clicks should increment by 1.
When you click the subtractBtn, the count of clicks should decrement by 1.
When the count reaches 0, the subtractBtn should disappear
The issue here is I need to somehow store this variable(count) into a variable that both controllers can read.
If anyone can answer how this could be done in Ext JS, that would be muy excellente and I will provide tons of upvotes. Thank you!
Use count as a global variable and here is a working example: http://jsfiddle.net/x_window/HVkhy/1/
Ext.onReady(function(){
var count = 0;
var btnAdd = new Ext.Button({
width: 50,
text: '+',
handler: function(){
++count;
if(count > 0 && btnSubs.hidden)
btnSubs.show();
if(count > 1 && !btnAdd.hidden)
btnAdd.hide();
}
});
var btnSubs = new Ext.Button({
width: 50,
hidden: true,
text: '-',
handler: function(){
--count;
if(count < 2 && btnAdd.hidden)
btnAdd.show();
if(count < 1 && !btnSubs.hidden)
btnSubs.hide();
}
});
var panel = new Ext.Panel({
width: 200,
items: [btnAdd, btnSubs],
renderTo: 'content'
});
});
I'm assuming the buttons have a common ancestor (maybe a container, or panel). You could keep the variable there. If you're using button handlers, you can access the parent container by using up()
handler: function(btn, e) {
btn.up('container').count++;
}
You may need to look over http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.ComponentQuery to figure out which selector to use for the up() function.
You can always access controller2 from a controller1 with the getController method of the application instance, which you get in the onLaunch method of controller1.
application.getController("controller2").count++;
Related
I have an event on one calendar, and I need to offer the user the ability to move that event to another month in the same calendar. It seems like the best way to do this is (1) remove the event from the current calendar, (2) create a draggable div outside the calendar, (3) allow the user to change the month/day/year, (4) allow the user to drag the div back onto the calendar, (5) hide the new div, (6) submit an ajax request to update the datasource, (7) delete the newly dropped event.
Attached are the code snippets used to do this.
My question: this seems very roundabout. Is there a better way?
// 1
reschedulingEvent = calendar.getEventById(....)
reschedulingEvent.remove()
// 2
rescheduledAppointment = new FullCalendar.Draggable(document.getElementById(
'rescheduled-appointment'), {
eventData: {
id: reschedulingEvent.id,
title: reschedulingEvent.title,
duration: "0:" + (reschedulingEvent.end - reschedulingEvent.start)/1000/60,
}
})
// 4
calendar = new FullCalendar.Calendar(document.getElementById('calendar'), {
editable: true,
droppable: true,
eventDrop: addEventToForm,
eventReceive: addEventToForm,
});
async function addEventToForm(info) {
if (!confirm("Would you like to reschedule this appointment")) return;
$(".rescheduled-appointment-div").hide() // 5
await axios.post(`/appointments/${info.event.id}`, {
start: info.event.start,
end: info.event.end,
}) // 6
calendar.refetchEvents()
calendar.getEventById(info.event.id).remove() // 7
If I have a list on a page, and it is using knockout's foreach binding to display list items, then something else updates the DOM to add an extra list item. If there any way I can get knockout to detect that DOM change and update its model to add the new item to the observableArray?
Here is a fiddle which shows the problem...
http://jsfiddle.net/BGdWN/1/
function MyViewModel() {
this.items = ko.observableArray([
{ name: 'Alpha' }, { name: 'Beta' }, { name: 'Gamma' }, { name: 'Delta' }
]);
this.simpleShuffle = function() {
this.items.sort(function() {
return Math.random() - 0.5; // Random order
});
};
this.simpleAdd = function() {
$("#top").append("<li>New item</li>");
}
}
ko.applyBindings(new MyViewModel());
It has 2 lists bound to the same observableArray, click the addItem button and you can see that the DOM is updated to include the new list item in the top list, but I would like the second list to be updated too, all via the model.
It seems that knockout ignores DOM elements that it didnt render, you can see this by clicking the shuffle button, it leaves the new items there. I would have expected it to remove them and do a full re-render.
Please don't answer with "Just add the item to the observableArray"
Take a look at the first link and the second link Interface MutationEvent
See Fiddle
$('#top').bind('DOMNodeInserted DOMNodeRemoved', function () {
alert('Changed');
});
I hope it helps.
I am trying to select events on fullcalendar, based on user selection.
Example: if user selects class A, then all classes with the same ID should turn green (using applied className).
I am having trouble applying classes to the other events that I can successfully select by ID. I guess my issue is combining the event objects with jQuery objects.
sample code:
eventClick: function(event) {
$(this).addClass("reg_selected"); //this works fine on selected event
var selectedID = event.id
alert(selectedID); //get event.ID, and use it to find similar ones.
var similarEvents = $("#calendar").fullCalendar('clientEvents',selectedID).addClass("reg_selected");
the error I get is:
addClass is not a function
I also tried this method of looping, and got the same error:
for (var i = 0; similarEvents.length > i ; i++){
alert(similarEvents[i].title);
similarEvents[i].className("reg_selected");
}
the alert() worked, but the className() generated the same error as above
This answer for a very similar situation, but when event classes are selected with round-trip to the event source for possible persistence in the db or checks.
Class name can be specified in the event object in the source as follows (start and end given for the context only):
[{
...
"className": "selected-event",
"start": '2017-05-01T08:30:00.0',
"ends": '2017-05-01T09:00:00.0',
...
}, ...]
The idea is that user clicks the event; ajax call to select events goes to backend; onsuccess, frontend javascript does$calendar.fullCalendar('rerenderEvents'); and receives the event source with events' classes. The immediate child of .fc-event-container gets the specified class, in the example above - selected-event.
As a result, the selection can be persisted on the backend.
clientEvents returns an array of matching objects. You need to iterate through the array (in your case similarEvents) and call addClass for each item
Update:
There is also issues using an id to update multiple events, using a filter function instead is a better way to go.
eventClick: function(event) {
var similarEvents = $("#calendar").fullCalendar('clientEvents', function(e) { return e.test === event.test });
for (var i = 0; similarEvents.length > i ; i++){
similarEvents[i].className = 'reg_selected';
$('#calendar').fullCalendar('updateEvent', similarEvents[i]);
}
},
See jsfiddle
For fullcalendar add event class, id and title see this.
if($('#eventTitle').val() == "Avilable") {
eventClass = "avilable";
}else {
eventClass = "unavilable";
}
$myCalendar.fullCalendar('renderEvent', {
id:response,
title: title.val(),
start: start.val(),
end: end.val(),
allDay: true,
className: eventClass,
color: color
}, true
);
I was able to get it working with the following code:
eventRender: function (eventObj, $el) {
$el.addClass(eventObj.ClassName);
},
eventObj.ClassName = "calendar-priority-warning"
I use jQuery fullCalendar (http://arshaw.com/fullcalendar/docs/selection/unselectAuto/)
I use Selectable version of this calendar (http://arshaw.com/js/fullcalendar/demos/selectable.html)
It's working fine however I want to cancel/delete my old selections if I continue selecting new dates.
Lets say I chose 1 Jan and gave a title to it.
When I try to select 2 Jan, I want to see only 2 Jan selection.
I thought unselectAuto is for this but I couldnt manage to make it work :(
Any ideas?
I used unselectAuto right under
selectable: true,
unselectAuto: true,
First it's still necessary to use the $('#yourCalendar').fullCalendar('unselect'); function.
The second thing that I needed to do, was to specify how the unselect callback was going to behave (when setting up the fullcalendar options). For me I had to unbind the submit button from my form
unselect: function(){
$('#submitButton').unbind();
},
It worked great!
I was able to reach this conclusion after reading this post "multiple events created"
u can try this way, this works for me :)
var liveDate = new Date(); // current Date
var calendar = $('#calendar').fullCalendar({
select: function (startDate, endDate) {
if (liveDate > startDate) {
alert('Selected date has been passed');
return false;
} else {
//do your wish
}
calendar.fullCalendar('unselect');
}
});
Had the same problem but my user was interfacing directly with the calendar and multiple events were being generated. ie. not through a form with a button and therefore nothing to "unbind" as many of the previous solutions.
To only allow one selection and to clear previous submissions I changed the select function as follows:
select: function(start, end) {
var title = "Desired Booking";
var eventData;
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); },
select: function(start, end) {
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('rerenderEvents')
var title = "Desired Booking";
var eventData;
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); },
This did the trick for me.
I had problems with unselectAuto also. Sometimes it would unselect when I didn't want it to, and sometimes it would NOT unselect when I DID want it to. My solution was to manually trigger the unselect method.
Here's how to unselect all currently selected:
$('#yourCalendar').fullCalendar('unselect');
You can put this line of code inside custom jQuery events that you bind outside of the plugin. You can also include it in fullCalendar callbacks, etc...
Hope this helps.
Scott
Here is an exemple of Version 5 doing the unselect
You could do it by :
const calendarApi = selectInfo.view.calendar;
calendarApi.unselect(); // clear date selection
Use this code
$('#trainings_modal').on('hidden', function () {
$('#trainings_modal *').unbind(); // Unbind all events
});
Unbind on hide form with any method (i.e esc press, or out key)
I have a dojo grid which is using some editable dijit form fields. All is well, until I try ot implement an country (multi) select cell as an Tooltip Dialog; i.e., show a drop down button which opens the tooltip dialog populated with a checkbox array to select one or more country. Once checked and clicked OK, the cell should update with a list of selected countries. Obviously I'll take care of updating the server via the store later on.
I've implemented a country select tooltip dialog which works fine like so:
dojo.provide("CountrySelector");
dojo.declare(
"CountrySelector",
[dijit.form.DropDownButton],
{
label: 'Countries',
dropDown: new dijit.TooltipDialog({ execute: function() {
console.log("EXECUTE : ", arguments[0]);
this.value = arguments[0].country;
}, href:'/cm/ui/countries' }),
postCreate: function() {
this.inherited(arguments);
this.label = this.value;
dojo.connect(this.dropDown, 'onClose', function() { console.log('close'); });
console.log("CountrySelect post create", this);
},
}
);
And the grid cell is typed as:
{ name: 'Countries', field: 'targeting.countries', editable: true, hidden: false, type:dojox.grid.cells._Widget, widgetClass: CountrySelector },
All is working fine but I can't figure out how to update cell's content and store once the widget is executed. As well, I don't seem to have the row id of the updated row.
Any ideas?
Thanks,
Harel
//Layout:
gridLayout: {rows: [{name: 'Coll Name',field: 'colField', type: dojox.grid.cells.ComboBox, editable:'true', width:'8%',options: [], alwaysEditing:false}]}
//Grid Store:
this.gridStore = new dojo.data.ItemFileReadStore({data: {items: data}});
//
var setOptions = function(items, request){
this.gridLayout.rows[0].options.push('Val 1','Val 2');
this.gridLayout.rows[0].values.push('1','2');
dojo.connect(this.gridLayout.rows[0].type.prototype.widgetClass.prototype, "onChange",this, "_onComboChange");
}
this.gridStore.fetch({onComplete: dojo.hitch(this,setOptions)});
_onComboChange: function (selectedOption) {
console.info("_onComboChange: ",selectedOption);
},
// If you need to populate combos with different values you can use onItem
var getArray = function(item, request){
// populate one by one
// attach an event to each combo
}
this.gridStore.fetch({onItem: dojo.hitch(this,getArray)});
This is what i used to update my grid
var idx = yourGrid.getItemIndex(item);
if (idx >- 1) {
yourGrid.updateRow(idx);
}
More detail
every row is identified by its identifier
yourGrid.store.fetchItemByIdentity({
identity: <yourIdentity>,
onItem: function(item){
// Update your attributes in the store depending on the server response
// yourGrid.store.setValue(item, <attribute>,<value>);
var idx = yourGrid.getItemIndex(item);
if (idx >- 1) {
yourGrid.updateRow(idx);
}
}
});
I didn't set up a test with your code but you should be able to do it by just creating a method named getValue in your widget that returns the value.
Take a look at the other examples (like dojox.grid.cells.ComboBox) to get an idea of what getValue should look like.