Jump to content
ryan

Events Fieldtype & Inputfield (How to make a table Fieldtype/Inputfield)

Recommended Posts

This module serves as an example of creating an editable table of data as a Fieldtype and Inputfield in ProcessWire. In this case, we create a simple table of events each with date, location and notes. This pattern can be adapted to nearly any table of information.
 
Note that this module is intended as a proof-of-concept. If you find it useful for the example scenario (events) then great, but keep in mind it is not intended as a comprehensive events solution, where using ProcessWire pages may be a better fit.
 
This is a pattern I've used for creating tables of data in ProcessWire for many different Fieldtypes/Inputfields and thought it would be good to setup a proof-of-concept example like this to share. 
 
 
screenshot.png
 
Install
  1. Copy the files for this module to /site/modules/FieldtypeEvents/
  2. In admin: Modules > Check for new modules. Install Fieldtype > Events.
  3. Create a new field of type Events, and name it whatever you would like. In our examples we named it simply "events".
  4. Add the field to a template and edit a page using that template.
 
Output
 
A typical output case for this module would work like this:
foreach($page->events as $event) {
  echo "
    <p>
    Date: $event->date<br />
    Location: $event->location<br />
    Notes: $event->notes
    </p>
    ";
}
This module provides a default rendering capability as well, so that you can also do this (below) and get about the same result as above:
echo $page->events;
...or this:
foreach($page->events as $event) {
  echo $event; 
}
Finding events
 
This fieldtype includes an indexed date field so that you can locate events by date or within a date range.
// find all pages that have expired events
$results = $pages->find("events.date<" . time());

// find all pages with events in January, 2014
$results = $pages->find("events.date>=2014-01-01, events.date<2014-02-01"); 
  • Like 26

Share this post


Link to post
Share on other sites

Thanks for sharing this :)

How scaleable with a look at the performance is this table solution? 

Share this post


Link to post
Share on other sites

@Xeto: Screen height would matter ! At 480 rows, your screen should be at least 2.5 meters high.

oké, seriously. all data is in the same table, so performance & scalability is good.

  • Like 1

Share this post


Link to post
Share on other sites

Ok, fine. I'm quite new with PW and have to compare solutions ;)

I build a accordion data table grouped by categories build with pages. With repeater / table field data is stored in fields of one page.

But you're right. Without accordion or pager the usability will be a bigger problem than the performance  :blink:

Share this post


Link to post
Share on other sites

Ryan,

This is excellent! 

What I'm doing now with repeaters looks similar, but it's a lot more work to setup, and not as clean.

Very much appreciated.

:)



Also, I love how the new admin is looking. That screenshot made me happy. :D

  • Like 1

Share this post


Link to post
Share on other sites
How scaleable with a look at the performance is this table solution? 

This is significantly more scalable and resource friendly than repeaters. It's directly connected to a single DB table without any other overhead. 

  • Like 3

Share this post


Link to post
Share on other sites

Indeed - it's a separate DB table like ryan says - if you take a look at the MapMarker module and a few others where they create their own tables you'll see that instead of just being a collection of different fields in their own tables like normal PW fields created in the admin these are like going back to a "normal" table with multiple fields.

Very useful for some situations where you don't need to re-use fields elsewhere and have a pretty bespoke dataset that needs to scale to potentially millions of rows.

This would also be good for things like invoicing systems, shopping carts etc where you want to store fields like item name, price, tax, total etc where you just wouldn't really need them as separate fields in the admin - they only make sense in the context of a single module. Which unfortunately means I need to change something I've done in an as-yet-unpublished module at some point to make it scale better :)

  • Like 2

Share this post


Link to post
Share on other sites

I am building a question answer website which may include voting, comments, and more...  I am expecting it to scale to millions of "rows" or "records".  The data does not need to be edited from the admin panel, but will be added by users of the site and displayed on the front end.  Typically, one question/answer to one website page.

My questions about this module:

1.  Is this solution here mainly meant for displaying this editable info in the admin?  

2.  Does it allow adding fields later on, even after the table is populated?

3.  For my scenario described above, Is using this module better than using pages for the questions, comments, votes, other stats?  

4.  Is this more scaleable, less resource intensive than using pages, for front end website display.

Your educated guess on this would be helpful. 

Share this post


Link to post
Share on other sites

@lundy - 1. yes; 2. fields (as far as i can tell) are hard coded into the module - you would need to clone the module and mod it for your use. 3. i don't think so. 4. probably not much if you use caching

  • Like 1

Share this post


Link to post
Share on other sites

If you are talking about one question and answer per page with a comments section beneath (or just a question with all answers as comments) then the current comments module would be your best starting point as it's already built to scale up.

If the questions will all be separate pages like Stackoverflow for example then you could just do that with a normal page. It matters less about scalability there as you would only display one at a time, or if browsing tthrough all questions you would paginate them with 20 to a page or categorise them some other way.

Share this post


Link to post
Share on other sites
1.  Is this solution here mainly meant for displaying this editable info in the admin?  

No, it's also more efficient (technically faster) on the front-end. 

2.  Does it allow adding fields later on, even after the table is populated?

It's possible, but you'd have to go in and add them directly in MySQL using PhpMyAdmin or the like, and update the module's code to recognize your new field. 

3.  For my scenario described above, Is using this module better than using pages for the questions, comments, votes, other stats? 

Probably not. While the database could handle millions of rows, the admin side won't be able to handle displaying millions of rows in the same page editor. It would be the same issue as with using a repeater, at least from the admin display aspect. Though this solution could technically serve a lot more rows than a repeater could.

4.  Is this more scaleable, less resource intensive than using pages, for front end website display.

It would not be as scalable as using pages, simply because everything around pages is already designed in consideration of scale (limits, pagination, selective loading of fields, etc.). Pages are certainly more resource intensive, but those resources go towards making them scalable. 

  • Like 1

Share this post


Link to post
Share on other sites

I just downloaded this module and wanted to try it out. However, when I try to edit the page with the assigned template/field I am getting this error.

Fatal error: Can not call constructor site/modules/FieldtypeEvents/EventArray.php on line 14

It is probably user error, but I cannot figure it out.

  • Like 1

Share this post


Link to post
Share on other sites

I have the same problem as Rjay: Fatal error: Can not call constructor site/modules/FieldtypeEvents/EventArray.php on line 14.

Hope somebody can help with this issue, tnx

  • Like 1

Share this post


Link to post
Share on other sites

Strangely I can't duplicate the issue, but the error message you guys have mentioned is correct. It was attempting to call a parent::__construct() even though the class it was extending had no __construct in the chain of classes. I'm guessing some versions of PHP care and some don't. I have updated the module to remove that call. Please let me know if it works for you guys now?

  • Like 1

Share this post


Link to post
Share on other sites

Hi Ryan, tnx for your quick reply!
 

The error is gone now. Just noticed a small styling error before first data input as you can see in the image below..

PW_Events.gif
 

  • Like 1

Share this post


Link to post
Share on other sites

Your addition did the trick Ryan, thanks! 

I am working on a stat based website that keeps track of statistical data for individual people ie age, weight, height, ect. This would be the perfect module for it instead of creating multiple fields using repeaters which in the long run would not scale from what I have read. Could you use page fieldtypes with this module, allowing the user to select from a preset list of pages/categories created in the admin area?

In the mean time I will be trying to figure out how to add new text and digit/float fields. I would also be interest in possibly sponsoring future development of this module to allow fields to be created on the fly since my php skills are sub-par. 

As always, thanks for providing it.

  • Like 1

Share this post


Link to post
Share on other sites
The error is gone now. Just noticed a small styling error before first data input as you can see in the image below..

That was in Firefox right? The issue was that the jQuery show() method defaults to showing it with "display: block". In order to display it correctly, Firefox needs it to be "display: table-row". This issue is fixed in the latest version, pushed out yesterday. 

Could you use page fieldtypes with this module, allowing the user to select from a preset list of pages/categories created in the admin area?

You certainly could. Though they wouldn't technically be Page fieldtypes, they would just be IDs of pages you gave them the option to select from your custom Inputfield. But you could make it behave just like a Page reference Fieldtype without much trouble. 

  • Like 3

Share this post


Link to post
Share on other sites

Hi Ryan, 

Thanks for the response. Great to know about the page id's and the possibility to make them behave like page references. I would like to pick your brain or someone's brain much more experienced then me if possible. 

I have been able to add new text fields relatively simply to the module, but was confused on one part.  In event.php  in the public get and set functions you sanitize the text values like so

else if($key == 'location' || $key == 'notes')

But lets say I wanted to add 5 or more text fields. Doing something like this seems incorrect?

else if($key == 'location' || $key == 'notes' || $key == 'another' || $key == 'another1' || $key == 'another2')

Also adding an integer field would be similar the the current date field?

Currently I am using repeaters to accomplish this and feel this module is a better fit although I still run into the issue at hand posted there.

Thanks for any suggestions.

  • Like 1

Share this post


Link to post
Share on other sites

But lets say I wanted to add 5 or more text fields. Doing something like this seems incorrect?

else if($key == 'location' || $key == 'notes' || $key == 'another' || $key == 'another1' || $key == 'another2')

If they should all be validated in the same way, then yes that's fine. Though I would usually convert something like this to this:

$validateTextFields = array('location', 'notes', 'another', 'another1', 'another2');

if(in_array($key, $validateTextFields)) {
  // validate text value
}
Also adding an integer field would be similar the the current date field?

If any integer is acceptable, you can sanitize just by typecasting the value to an integer:

$cleanValue = (int) $dirtyValue; 
  • Like 3

Share this post


Link to post
Share on other sites

Awesome Ryan! Thank you for your time and clearing the murky water for me and hopefully others.

Share this post


Link to post
Share on other sites

Would it much work to build it as a universal module? Maybe with a config file to match the database table fields?

So everybody can use it independent of use case.

Just an idea. Maybe to much work to do it.

  • Like 4

Share this post


Link to post
Share on other sites
Would it much work to build it as a universal module? Maybe with a config file to match the database table fields?

So everybody can use it independent of use case.

That universal module is called ProcessWire. :) 

In all seriousness, I understand what you are saying. This Events fieldtype isn't particularly useful in it's standard state. It is meant purely for you to take and extend it to do what you want with it. It might also be useful as a starting point for someone wanting to make a fully configurable version of it. But as to how "much work" it would take, it would not be a small project. 

  • Like 2

Share this post


Link to post
Share on other sites

This module would be awesome if it wasn't tied to only events, it might be reworked to build dynamic table data.

I have a case where i need to make several dynamic tables of information and I need column titles that get defined once, with each row of columns below with repeatable data and the UI for this "events" fieldtype looks like a starting point.

Otherwise I have to mismash a solution where a user might not put in the right amount of rows or columns, because they can't see everything at once

You know how tables work:

column-title1, column-title2, column-title3 (this row is set once)

row1col1-data, row1col2-data, row1col3-data (these rows repeat)

row2col1-data, row2col2-data, row2col3-data

row3col1-data, row3col2-data, row3col3-data

...

Now being able to build that dynamically and dynamically set the # of columns and rows, would be very powerful.

Share this post


Link to post
Share on other sites
This module would be awesome if it wasn't tied to only events, it might be reworked to build dynamic table data.

@pers0n: go back to the first page in this thread. :) Events are not the purpose of this fieldtype. Events are just used as an example. The purpose of this fieldtype is for you to modify it specific to the data you need to represent, whether a table of inventory, prices, people, or any kind of tabular data you want. Even if you actually wanted to use it for events, you'd still want to modify it for the type of events given that it's not that useful in it's demonstration state. This fieldtype is meant to be changed by you.

  • Like 3

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...