Next and Previous month watcher in Vue FullCalendar - vue.js

I'm using FullCalendar library with Vue.js
Is it possible to use the default prev, next and today buttons that are default to trigger my own actions.
I have created my customs buttons that do what I want, but prefer to use the default buttons.
Current I have a button linked to a method:
<button #click="handleMonthIncrement">Next Month</button>
And this calls this method:
handleMonthIncrement: function(arg) {
// update month and year
this.incrementMonth();
// update calendar
let calendarApi = this.$refs.fullCalendar.getApi();
calendarApi.next();
// updateCurrentSummary (mapped to store)
this.updateCurrentSummary();
}
I'm using the ref=fullCalendar which ties into the jQuery reference of the Calendar to change the view.
If I could listen to the next, prev buttons then I could remove that code as the buttons already change the calendar view.
Is this possible? I'm aware that viewRender (https://fullcalendar.io/docs/v1/viewRender) can be used to note when the calendar has changed view, but am not sure if this is something that can be used for my requirements above.
Thanks in advance.
Thanks

I achieved this by looking up the Events Emitted here: https://github.com/fullcalendar/fullcalendar-vue/blob/master/src/fullcalendar-options.js
And I found datesRender - which can be added to the FullCalendar element prefaced by # to trigger when the dates re-render. Because I have this on month only view I can then trigger a method which I called handleMonthChange.
See here:
<FullCalendar
defaultView="dayGridMonth"
#datesRender="handleMonthChange"
/>
Then within handleMonthChange I had the following:
handleMonthChange: function(arg) {
var currentStart = arg.view.currentStart;
var check = moment(currentStart, "YYYY/MM/DD");
var currentMonth = check.format("M");
// load action
this.updateCurrentMonth(currentMonth);
// refresh summaries
this.updateSummary();
}
I used moment to determine the month from the date (from the view object.
See more info here on what is passed back here https://fullcalendar.io/docs/datesRender
I then used this to change the month in my Vuex state by calling a Vuex action, then I updated my summary section as required.
Hope that helps someone else too. Big thanks to #ADyson for helping me get here!

Related

VueJS: Computed Property inside a loop

My scenario is that of the picture:
I have some transaction headers and transaction details. The screenshot is a pop-up dialog for editing a transaction...
One transaction could be a member ship fee. If a member pays a fee (see 1) then I want to be able to enter the month related to the fee.
Each "Buchungsvorgang" (transaction detail) is being looped through with v-for:
<v-row
v-for="(item, index) in editedItem.transactionDetail"
:key="index"
dense
align="center"
class="mb-2"
>
I also want to show the months for which a member has already paid previously.
I have set it by:
When the name (see figure 1) is changed call a method:
async showMonths (idPerson) {
try {
const response = await this.$axios.$get(`/api/api.php/records/transactions?filter=idPerson,eq,${idPerson}&size=5`)
this.lastMonths = response.records
.map((item) => {
return `${this.$moment(item.month, 'YYYY-MM').format('MMM YY')} - (${new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(item.Amount)})`
})
.join(' // ')
} catch (e) {
this.lastMonths = e.message
}
}
This works perfectly. It's an async function as it always picks up the latest info directly from the database.
So each time, if a change the member (see number 1), the output changes.
My problem: It only changes when someone triggers the change event of the form. If I open the dialog, number two would be empty because no one triggered the event in the first place.
This is the way it looks when I open the dialog.
Question:
Can I use a async computed property here and as a parameter, pass the editedItem.transactionId to the prop in order to retrieve the data?
Or can I put the method inside the data () - function? I want the output to be visible all the time, not just if someone clicks on a field.
I have created to small codepen to illustrate the problem:
https://codepen.io/rasenkantenstein/pen/qBdZepM
The first form (person.name) is meaningless. However, the city is the variable equal to figure 1. The result should be printed as the :message property of figure 2 (city).
How - when loading the codepen - can I populate both details?
I've updated your codepen that does what I think you want, see example.
Essentially, you just set your messages on either created or mounted hooks:
created: function () {
this.people.forEach((item, i) => {
Vue.set(this.message, i, item.country)
})
}
The key thing to note above is the use of Vue.set, since Vue cannot detect changes to an array when you directly set an item with the index, see the documentation around this. So I recommend you use Vue.set inside your changeCity function as well.

How to hook into a change in the model in a widget

I'm trying to respond to a change in one of the properties of the model in a widget. To be clear, when the value of the property changes, I want to run some code to react to the change. In a parent widget I have a date picker which changes the date in the model.
I cannot get the custom setter to be called _setParentPropertyAttr...
If I include this in my widget
<span data-dojo-type="dojox/mvc/Output" data-dojo-props="value: at(rel:, 'ParentProperty')">
It works nicely. Changing the date picker outputs the current value to the page. So I can supply the value property to the output widget when the date changes in the model. But what I need to do (I think) is supply a custom property with the date property in the model when the date picker changes the value.
I realise this question is a bit vague but I can't provide the code as it's proprietary.
I've tried to break the problem down by setting a property manually within my widget as:
myProperty:0,
...
constructor
...
_setMyPropertyAttr: function(value):
{
console.log("setting myproperty");
}
....
this.set('myProperty', 5);
....
but that isn't working either.
If you set a property within a widget does that not call the custom setter?
I'm struggling a bit because there aren't so many dojo examples out there any help is much appreciated.
You can bind an event to be called when a widget's property is set/update or you can even use watch to do that.
But this only works using the set function, using someWidget.someProperty = 5; wont work.
Let me show you how dojo do it. The basic about the magic setters and getters is explained here.
_set: function(/*String*/ name, /*anything*/ value){
// summary:
// Helper function to set new value for specified property, and call handlers
// registered with watch() if the value has changed.
var oldValue = this[name];
this[name] = value;
if(this._created && !isEqual(oldValue, value)){
if(this._watchCallbacks){
this._watchCallbacks(name, oldValue, value);
}
this.emit("attrmodified-" + name, {
detail: {
prevValue: oldValue,
newValue: value
}
});
}
}
This peace of code is from dijit/_WidgetBase, the _set function is what dojo calls after a set is called, and is where it finally set the property value this[name] = value; and as you can see, it emit an event that will be called attrmodified-propertyName and also call a watchCallbacks.
For example, if in some place, we have this:
on(someWidget, 'attrmodified-myproperty', function(){
console.log(someWidget.get('myProperty'));
});
and then we use:
someWidget.set('myProperty', 'Hello World!');
The event will be triggered. Note that someWidget.myProperty = 'Hello World!' wont trigger the event registration. Also note that if in our widget we define the magic setter:
_setMyPropertyAttr: function(value) {
//do something here with value
// do more or less with other logic
//but some where within this function we need to cal "_set"
this._set('myProperty', value);
}
without calling _set, the magic wont happen.
As i said at the beginning, we can also use watch:
someWidget.watch('myProperty', function(){
console.log(someWidget.get('myProperty'));
});
Note that we can register to this events or the watch function within the same widget.
Also, as a plus, the magic setter can be triggered when creating the widget with just passing the property name in the constructor object param, this work for the declarative syntax too, for example:
var someWidget = new MyWidget({
'myProperty': 'Hello World!!'
});
and
<div data-dojo-type="MyWidget" data-dojo-props="myProperty: 'Hello World!!'"></div>
both will triggered a call to the _setMyPropertyAttr if exist, or dojo will use the magic setter in the case it doesn't exist.
Hope it helps
Consider using custom setter on your widget, where you can add your custom logic.
Example of definition of custom setter on your widget:
_setOpenAttr: function(/*Boolean*/ open){
// execute some custom logic here
this._set("open", open);
}
Example of setting a property on your widget:
widgetRef.set('open', true);
Alternatively you can could consider using dojo/store/Observable.
dojo/store/Observable store wrapper that adds support for notification of data changes.
You can read more about it on the followign link:
https://dojotoolkit.org/reference-guide/1.10/dojo/store/Observable.html
If figured out the problem. If I set a watch on the model I can then check if indiviual properties have changed in the watch function. I knew it would be something simple!

Sharing information between Polymer 1.0 modules

I have two components inside a parent, one component shows me a list, and I want the other component to show me the details of an item of the list. I'm using the List of this demo https://elements.polymer-project.org/elements/neon-animation?view=demo:demo/index.html&active=neon-animated-pages
since I have these two components
<list-view data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view on-close="_onClose"></full-view>
I would like to pass the Id of an item clicked on list-view to the full-view. So what would be the best way to execute an event on "full-view" when an item of "list-view" is clicked? I need to pass information from list-view to full-view.
Thank you.
What about of databinding? #SG_ answer is ok, but it can does using simple databinding, as follows:
<list-view data="[[fileData]]" on-item-click="_onItemClick" selected-id="{{idSelected}}"></list-view>
<full-view on-close="_onClose" selected-id="{{idSelected}}"></full-view>
Each element models should have a property "Selected ID", to make it possible to perform databinding. In <full-view> you must need to add a property as follows:
selectedId:{type:String, observer:"selectedIdChanged"}
So, when selectedId changes in <list-view> will also change in <full-view>
Now, you only need to add a new function in <full-view> to do something with this changed selectedId
selectedIdChanged: function(newValue, oldValue){
if(newValue!= undefined && newValue!=null){
//do something with selected Id
}
},
You could give an id for both list-view and full-view, then define & set data attribute/property for <full-view> from the _onItemClick.
<list-view id='l_view' data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view id="f_view" data="{}" on-close="_onClose"></full-view>
And in the script of parent.
_onItemClick: function() {
this.$.f_view.data = this.$.l_view.selected;//or any attribute of the selected item
this.$.pages.selected = 1;
},

dojo/form/select onchange event not working for me in dojo 1.8

I am trying out dojotoolkit 1.8 and cant figure out how to hook up an onchange event for a dojo/form/select
Nothing happens with this
require(["dojo/dom","dojo/on"], function(dom,on){
on(dom.byId("myselect"),"change",function (evt){
alert("myselect_event");
});
If instead, the following hook into click works:
on(dom.byId("myselect"),"click",function (evt){
but i want to capture the value after user clicks and changes
I am sure it is simpler than going back to Plain ol javascript onChange...
Thx
You could try something like this:
var select = dijit.byId('myselect');
select.on('change', function(evt) {
alert('myselect_event');
});
I've seen this in the reference-guide multiple times, eg in the dijit/form/select' s reference-guide at 'A Select Fed By A Store'.
Maybe it even returnes the handle, i haven't looked this up so far. But i guess it should work.
EDIT:
Considering #phusick's comment, i want to add, that you could also simply change the "change" to "onChange" or the dom to dijit within calling on(...)
Following in the footsteps of #nozzleman's answer try
var select = registry.byId('myselect');
select.on('change', function(evt) {
alert('myselect_event');
});
If you use on instead of connect then you don't have to write onChange, you can simply write change.
Similar to above answers do a dijit.ById to find the correct element and then register the 'onItemClick' event.
creating the select dropdown programatically appends a _menu to whatever node you create the select items so 'search' becomes 'search_menu' on a page init you can do the following:
dojo.connect(dijit.byId('search_menu'),'onItemClick',function(){
//console.log("search menu");
doSearch('recreation');
});
As others have pointed out, you're trying to access the Dijit using DOM. Also, the parameter to the anonymous function for the "change" event is the value selected by the user, not the event itself.
Here's your code modified to access the Dijit and process the "change" event:
require(["dijit/registry", "dojo/on"], function(registry, on) {
on(registry.byId("myselect"), "change", function (value) {
alert("change_event.value = " + value);
});
});
Late to the party, but I recently ran into the issue. Hopefully my answer will help some poor soul maintaining some legacy code. The answer is for combobox but worked for select as well -
onChange not sufficient to trigger query from Dojo Combobox. Need to attach listener to dropdown items.
select.dropDown.on("itemClick", function(dijit, event) {
var node = dijit.domNode;
console.log(domAttr.get(node, "data-info-attribute"));
// or
console.log(node.dataset.infoAttribute);
});
Ref: https://stackoverflow.com/a/12422155/4564016

Calling member functions on click/tap within sencha touch 2 templates

I am rather new to sencha touch, I've done a lot of research and tutorials to learn the basics but now that I am experimenting I have run into a problem that I can't figure out.
I have a basic DataList which gets its data from a store which displays in a xtemplate.
Within this template I have created a member function which requires store field data to be parsed as a parameter.
I would like to make a thumbnail image (that's source is pulled from the store) execute the member function on click/tap.
I can't find any information on this within the docs, does anyone know the best way to go about this?
Here is a code example (pulled from docs as I can't access my actual code right now).
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>'
{
tapFunction: function(name){
alert(name);
}
}
);
tpl.overwrite(panel.body, data);
I want to make the paragraph clickable which will then execute the tapFunction() member function and pass the {name} variable.
Doing something like onclick="{[this.tapFunction(values.name)]} " does not seem to work.
I think functions in template are executed as soon as the view is rendered so I don't think this is the proper solution.
What I would do in your case is :
Add a unique class to your < p > tag
tpl : '<p class="my-p-tag">{name}</p>'
Detect the itemtap event on the list
In your dataview controller, you add an tap event listener on your list.
refs: {
myList: 'WHATEVER_REFERENCE_MATCHES_YOUR_LIST'
},
control: {
myList: {
itemtap: 'listItemTap'
}
}
Check if the target of the tap is the < p > tag
To do so, implement your listItemTap function like so :
listItemTap: function(list,index,target,record,e){
var node = e.target;
if (node.className && node.className.indexOf('my-p-tag') > -1) {
console.log(record.get('name'));
}
}
Hope this helps