[HOW-TO] Create a custom Calendar using repeating group

Hello all! Update for everyone.

If you are interested in having a week view for your project, you can use this code now!

function getDaysInWeek(e,t){var a=new Date(e,0,1);a.setDate(a.getDate()+7*(t-1));var D=a.getDay();for(s=0;s<D;s++)a.setDate(a.getDate()-1);for(var n=new Date(a),r=[],g=[],s=0;s<7;s++)r.push(n.getDate()),g.push(new Date(+n)),n.setDate(n.getDate()+1);return g}

This will return 7 days of the week you pass it starting from Sunday.

Live Preview: Click
Editor: Click

If there is enough of a demand I can create a step by step tutorial for creating this, otherwise you can simply copy with workflows and paste into your app or view the editor to see how it is built.

Thank you,
Nic | nic@codurly.com
codurly.com
image

15 Likes

Hi,

is it possible to do the exact same thing but with a day view? iā€™d like to create a repeating group, displaying a 24 hours date range with a increment of 15 minutes. Its a bit more tricky than i thought it would beā€¦

Thanks :slight_smile:

1 Like

Is there an issue with the week view. I noticed that today on Sunday it doesnā€™t open correct week on page load. It still shows a previous week. I couldnā€™t find a way to fix it.

Hey Nick,
Is there a way to start a week view on a Monday?

2 Likes

@ItsJustBusiness I would 110% be ecstatic to see a tutorial on how you did these calendars.

I have followed the tutorial on this thread and found it extremely helpful. These others in this example are just like what I need for my project, so I would love to see the tutorial, or if could post the editor of these so I could see how things are set up and give it a go on my own.

Thanks again for posting this. Extremely helpful.

Cheers

2 Likes

I think he set those up so you can see his editor for those.

This is a very powerful technique in general and you can do a lot with it. It can be a TOUCH slow (particularly on some mobile devices) depending on if youā€™re doing a lot of conditional styling. Issue being that a 42 element repeating group can generate A LOT of on-page elements and conditions.

If you want to see an absolutely insane extension of this idea, see this page:

@keith Thanks for that. I did some digging and found my way to the editor.

I checked out your link as well, that is pretty cool to get the languages to change. Iā€™ve been needing to find some good tutorials or forum posts about how to use bubbleā€™s built in language feature. From what I can tell it requires passing through the URL the lang=(users preferred language).

Iā€™m actually using the calendars to build out the administrative portion of my booking site and was expecting it to take a couple of weeks as I had no idea what I was doing. Now with this post and the editor views I feel it will take a few days. Very excited to knock it out.

Thereā€™s not really a built-in facility for multiple languages beyond handling various error messages and built-in element labels (this is known as the ā€œapp textā€ feature). But of course you can extend that.

For a very brief explanation of how I added the multilingual feature to my calendars, see the end of my Medium article here:

Iā€™ve been playing around with this and have no idea about coding. I was able to make the calendar show a two week or any number of day display I set.

What I am curious about is how to get the first day of the calendar displayed to be the current date. Instead of always starting on Sunday or Monday, is there a way to get the current date to be the first in the repeating group?

1 Like

Yep, just write a function to return an array of 42 (or however many you need) date objects. And return that from the expression.

Like a variation on this:

https://www.dyclassroom.com/javascript-code/create-an-array-of-dates-between-start-date-and-end-date-in-javascript

haha @keith I was just looking at this : https://www.w3schools.com/js/js_dates.asp

Will post what code I can come up with to start the repeating group on the current date and not a specified day of the week.

1 Like

So, I canā€™t spend anymore time playing around on this today. I donā€™t know how to code (why Iā€™m using bubble), so I donā€™t think I will be able to come up with a way to rewrite the expression to set the first date in the repeating group to the current date.

If any coders could help out that would be much appreciated.

Also, on but off topic; To fully take advantage of bubble, it seems knowing some code is necessary. If I want to be able to do more, what languages are recommended to learn to a beginner level that would help me do more in bubble. I feel javascript is necessary as that is what is used in expressions.

Are there any other languages that I could use in bubble to get more from it?

I want to write expressions and connect APIs from outside platforms.

While you can do all sorts of web stuff in a variety of languages, JavaScript is the thing you want to focus on. Hereā€™s why:

At the end of the day, Bubble is simply a very powerful and easy-to-use system for building websites and web applications (which one might just call ā€œreally fancy websites with dynamic stuff and a database backendā€ :wink: ). Backend technologies can vary widely, but websites and web apps really just boil down to the following (simple but powerful) technologies:

  • HTML (the basic markup language of web pages)
  • CSS (cascading style sheets/styling properties of HTML things)
  • JavaScript (the universal language of web browsers and other web clients)

Web browsers as we know them today arenā€™t just simple applications that display information in HTML. They are, in fact, powerful programming environments. You can think of them as a program that runs programs. Those programs are composed mostly of the three elements above.

Bubble makes it really easy to build pretty complex things on the backend/server side, while also helping you style/design pages and do some pretty fancy stuff in the browser. But like any web site/app authoring tool, you can extend it a HUGE amount with a little JavaScript. (In fact, you wonā€™t get far with ANY web authoring tool or service without learning ā€“ even just by osmosis ā€“ how websites work.)

(Even if youā€™re just authoring a static-ish site with something like Squarespace or Wix, a little knowledge of these core web technologies greatly extends what you can do. So Bubbleā€™s not unique in the respect. What youā€™re doing with Bubble is building web things.)

A while back, I made a very simple video that shows how easy it is to do very basic, simple stuff with just a tiny bit of JavaScript and the Toolbox plug-in. Check this out and you might get hooked:

JavaScript is basically the thing youā€™d want to learn vis-a-vis building more advanced websites and web apps in Bubble. And really, you can learn it piecemeal ā€“ you might be surprised how development in any language actually works in many cases. Basically, someoneā€™s always done more-or-less exactly what it is you want to accomplish. And somewhere, someone has already asked "how do you do ā€˜Xā€™ in JavaScript?'ā€¦ and multiple someones have provided answers on various approaches.

So Google (and StackExchange and sites like that) are your pal!

As far as APIs go. If you know some JavaScript you can write not just browser-side stuff now, but server-side stuff as well. JavaScript is so well understood (and has become a really great, very modern, and more-or-less easy to write programming language) that thereā€™s a thing called ā€œnode jsā€ that is JavaScript, but for using on a server or any sort of device thatā€™s NOT a web browser.

Node is basically just JavaScript. Itā€™s a way of running JavaScript in other places than in a web browser. There are a variety of ways that you can run JavaScript on a server running Node that are fairly easy to get started with: Namely Amazon Web Services ā€œLambdaā€ and Webtask.io. These are whatā€™s called ā€œfunction as a serviceā€ services. They basically just let you plop down and run some code and return the results of that code over the web. So they can be used to make what are essentially your own APIs really quickly (Webtask is the much easier of the two, in my opinion).

Without going on for much longer: What makes Node so awesome is that there are tons of libraries for doing fancy things that are open source. These libraries are all available in a thing called NPM thatā€™s completely integrated with Node. (And in Webtask thereā€™s actually a point-and-click environment for loading libraries from NPM ā€“ you can install anything thatā€™s in NPM super easily without mucking around with command-line stuff.)

BTW, most NPM libraries are also available in plain-old-JavaScript and can be loaded in a web page and used right in your Bubble pages (in the browser). But I find looking for things on NPM to be much easier than looking for things on GitHub (which is the service where everyone posts and hosts their open source projects).

Hereā€™s a post of mine that gives you a specific example of how loading a library and using it in a Bubble page works (not a tutorial, but Iā€™m saying, ā€œHereā€™s a line of code you can use to do what seems like a very hard thingā€ [youā€™d execute that in a Run Javascript action from the Toolbox plugin] and then I note what libraries you need to load to be able to execute that line of code):

Note: perhaps I should branch this thread. :stuck_out_tongue:

10 Likes

Great tutorial, Thanks! I have another question. Whatā€™s the best way to combine this with showing timeslots per day? So I want an offset of 30 minutes and show these time-segments of the specific day in a repeating group.
I have an example here: https://bubble.io/page?type=page&name=agenda_test_new&id=agendazc&tab=tabs-1

Any tips and/or help would be really helpfull:)

1 Like

Very nice tutorial, thank you very much!
I would like to implement this with a view of a full year.
Is there a place I can learn to master JavaScript on a basic level in order to implement this?

You can do this (theoretically). What the expression code does is generates the 42 dates that should be shown in the calendar.

You could generate more dates here. (But right you need to be able to write the code for that.)

The issue youā€™re going to hit is that, extending this technique to draw a full year calendar is going to generate A LOT of repeating group elements and potentially be very slow or even crap out on certain browsers. (The Calendar is drawn via a repeating group.)

I do use a variation on the technique described here for an app of mine that makes calendar widgets.

See https://grupz.com/vacation-rental-calendar and youā€™ll see links to a 3-month calendar view.
(edit ^^^ fixed typo in url)

You might note that there is maybe a bit more slowness and lag to that widget than youā€™d ideally want. And this is why I donā€™t offer a 12-month view, as the issue gets worse.

The solution would be to write a more performant display component as a plug-in. This is something I might do at some point, but thatā€™s not a near-term thing!

1 Like

Hey,

We plan on working on a plugin with more fuctionality as well as a new tutorial that will offer more features such as month/year selection. Be sure to follow the thread

Thank you,
Nic
codurly.com/assist

1 Like

Hereā€™s a direct link to an example 3-month view calendar built with this technique:

Note that, in my version, Iā€™ve highly modified the date-generation code (I use the moment.js library and related libraries to generate dates and handle some slightly complex timezone manipulation stuff).

Aside: another thing that impacts the performance of my calendar widgets is the way that I compute and identify the blocked dates. Basically, reservations come over to GRUPZ via iCal feeds. The blocked dates are represented by start and end dates. The individual calendar dates do a range-wise search to find out if they are within a booked range and a condition on that element in the RG/Calendar sets their color based on that.

There are faster ways to do that, but for various technical reasons, this is the way it works today. (A somewhat faster approach is to instead use a list of individual blocked dates and set the conditions that way. This is possible in my app (and in fact I do pass a list of such dates), but the rangewise comparison is actually the ā€œbetterā€ and more maintainable way for this to work.

Iā€™m always working on little tweaks to improve performance. (One that occurs to me now is that I think the range-wise comparisons are always done over a propertyā€™s entire future bookings, not just the ones that are ā€œin viewā€ in the displayed calendar. There may or may not be an advantage to changing the way I do that. One issue is that these comparisons are (of necessity) in a :filter condition (because they need the ā€œAdvancedā€ comparator) and so they are evaluated in the browser / on the client side. This somewhat limits the number of available performance enhancements that are possible.)

The reason I mention all of the above is that (1) in oneā€™s own application of the custom calendar technique, you might get better or worse performance than what I get, depending on what it is youā€™re doing and how youā€™re doing it and (2) in my particular application, thereā€™s a lot of stuff going on in the browser and so itā€™s very sensitive to the clientā€™s compute power.

(So, if you think my calendars suck or are sub-optimal, thatā€™s on me, not on the general coolness and power of the custom calendar technique in general! :wink: )

Great tutorial! Exactly what Iā€™ve been looking for (to a point anyway)! Thanks for posting it!

I have created a nice custom calendar for my event-planning app, but I am running into an issue recreating a feature of the Full Calendar plugin.

My events have the possibility to span multiple days (EventStartDateTime and EventEndDateTime are several days apart).

With the Full Calendar plugin an event spanning multiple days shows up as one (clickable) consecutive line spanning the corresponding date squares.

To display a full list of events on each day in the calendar I am using a repeating group to show all events on the current cellā€™s date (with hour, minutes and seconds set to 0).
Of course that way each calendarā€™s cell is limited to showing events each corresponding with the specific date of the cell and not for dates before or after - which is of course needed to show events on multiple consecutive days.

I can get multiple days-view using @ItsJustBusinessā€™s example, but thatā€™s using a date picker on the page to display

I think I should be using several :merged "search for"s, but I canā€™t seem to get it to work.

What logic am I missing here? Any ideas or tips would be really helpful and greatly appreciated!

maybe @ryan8, @ItsJustBusiness, @codurly?

Update: Iā€™ve found a partial solution.

I am now using 3 separate :merged "search for"s:

1 for events that start ON the cellā€™s date (with 2 constraints:

  • StartDateTime ā‰„ Current cellā€™s date change hours to 0 change minutes to 0 change seconds to 0
  • StartDateTime ā‰¤ Current cellā€™s date change hours to 23 changes minutes to 59 change seconds to 59

1 for events that start BEFORE the cellā€™s date but end AFTER the cellā€™s date (ie. inbetween):

  • StartDateTime ā‰¤ Current cellā€™s date change hours to 0 change minutes to 0 change seconds to 0
  • EndDateTime ā‰„ Current cellā€™s date change hours to 23 changes minutes to 59 change seconds to 59

1 for events ending ON the cellā€™s date:

  • EndDateTime ā‰„ Current cellā€™s date change hours to 0 change minutes to 0 change seconds to 0
  • EndDateTime ā‰¤ Current cellā€™s date change hours to 23 changes minutes to 59 change seconds to 59

Using this method events spanning multiple days are shown on each of itā€™s days. Not as a continuous line yet, but that might be solved using conditional forwarding.

Maybe thereā€™s an easier way that described here and maybe someone already tackled all of this - if so let me know :wink: