Widget Developer Documentation

Storing Data into Content Sets

The Moboom platform allows you to write widgets which store data in the platform. There are two different operations a widget can perform: storing data into content sets, and uploading images into the library.

Saving to content sets

You should already be familiar with how to load data from content sets into your widget. See the Collections & Content Sets page for details. This section describes how you can write widgets which allow users to store data into a content set. The API which accomplishes this is Moboom::updateContent().

For this example, we will be building a small system to manage sports teams. The content set will have the following fields for each team:

  • id - a unique code, for internal use only
  • teamName - the name as shown to users
  • captain - the name of the team captain
  • logo - an image to represent the team

This first example will show you how to manage the two text fields (teamName and captain). Later in this tutorial we’ll see how the user can upload an image. All of the code samples are fragments; the exercise of tying everything together into a working widget, or set of widgets, is left to the reader.

Build the form

The first piece of code is the form that the user will use to submit their content. The code below loads the data from the widget settings, and uses them as the starter values for the input fields. In this case, the form will post back to the same URL that it is displayed on.

<?php
$name    = Moboom::getWidgetSetting( 'teamName');
$captain = Moboom::getWidgetSetting( 'captain');
$teamId  = Moboom::getWidgetSetting( 'id');
?>
<form action="" method="post">
    <input type="text"   name="name"    value="<?= $name ?>" />
    <input type="text"   name="captain" value="<?= $captain ?>" />
    <input type="hidden" name="teamid"  value="<?= $teamId ?>" />

    <input type="submit" name="submit" value="submit" />
</form>
Process the form

What happens when the form is submitted? Clearly we ought to do some validation, both client-side and server-side, although that essential step is omitted from this tutorial. After validation, we can save the new data into the content set. 

Saving to a content set requires two essential pieces of information:

  1. A reference to the content set itself, and
  2. The internal ID of the record you wish to edit.

To get a reference to the content set, create a widget setting using the data type Content Select. This will let the widget user choose from a list of content sets in your site.

The record ID is passed in a hidden form field, as shown in the code above.

The third piece of information needed to save data into the content set is a list of fields to update.

<?php
if ( !empty($_POST['submit'])) {

    // get the reference to the content set
    //
    $contentSetId = Moboom::getWidgetSetting( 'cs');

    // get the ID of the team being edited
    //
    $teamId = $_POST['teamid'];

    // create an array of fields to store. the keys
    // must match field names in the content set
    //
    $fields = array(
        'teamname' => $_POST['name'],
        'captain ' => $_POST['captain']
    );

    // store the content! this is an asynchronous request
    // which does not begin until after the widget has
    // finished rendering
    //
    Moboom::updateContent( $contentSetId, $teamId, $fields );

    // send the user to the the thankyou page
    //
    Moboom::redirectTo( Moboom::createUrl( '/thank-you'));
}

There isn’t much code in the sample above. Be sure you understand how the pieces fit together. On line 15 we convert the form fields into an array, which is how the API expects to see the data. The unique record ID (in this case, $teamId) is not included in this array; it is a separate parameter to Moboom::updateContent() on line 24. The keys in the $fields array must match field names in your content set. The associated values will be stored into the content set without additional error-checking.

Note
If any key in the $fields array does not match the name of a field in the content set, a new field will be created. This gives you a lot of flexibility in managing your content set, but use with caution! Your content set can quickly become littered with unused fields if you aren’t careful.
Multi-level structures

If your content set is structured more than one layer deep — for example, an address field that is made up of separate fields for city, state, and postal code — you can include that structure in the $fields array.

This is a situation that typically would only arise using a synched content set. For example, if you import an XML file that has multi-layer structure, you can edit its contents using arrays within arrays.

<?php
$fields = array(
    'teamname' => $_POST['name'],
    'captain ' => $_POST['captain'],
    'address'  => array(
        'city'   => $_POST['city'],
        'state'  => $_POST['state'],
        'postal' => $_POST['postal']
    )
);

This is an advanced topic. We encourage you to experiment with a small content set to see how it works.

Other content-related APIs

In addition to Moboom::updateContent(), there are two APIs that may prove useful when working with content sets.

First, Moboom::addContent() allows you to create a new record. You can do this with Moboom::updateContent() as well (by passing null for the second parameter), but addContent() may be easier to read and understand.

There is another API available for editing content. Moboom::contentReplace() is similar to Moboom::updateContent(), except that contentReplace() will delete the old record before saving the new one. This is useful when your content set has either optional fields or arrays of unspecified length (such as tags or categories). If you use Moboom::updateContent() with an array of tags, you may find it hard to remove old tags.

In fact, you may find that you only need to use Moboom::addContent() and Moboom::contentReplace(), which together are both more predictable and more explicit than Moboom::updateContent().

Uploading images into the library

Images can be uploaded easily from within the studio. But you can also write a widget that lets a site visitor upload an image to the library without having access to the studio. These images are stored in the main Moboom library.

Moboom provides an AJAX endpoint called _upload. If you submit an image to this address, as part of a form POST operation, you will receive the ID of that image in the library. The ID can in turn be stored into your content set using the techniques described above.

Here is how to construct the form. Comments follow.

$url          = parse_url( Moboom::getRequestUrl());
$ajaxEndpoint = $url['scheme'] . '://' . $url['host'] . '/_upload';
?>
<form action="<?= $ajaxEndpoint ?>" method="post" class="imageForm"
      enctype="multipart/form-data">
    <input name="file"    id="imageInput" type="file" />
    <input type="submit"  id="submit-btn" value="Upload" />

There are some important things to note about the way the form is built.

The endpoint URL needs to be created exactly as shown above, to ensure that the form uses the proper scheme (http or https) and host.

Also, and the code for this is not shown above, the form needs to be processed using AJAX, rather than allowed to submit normally with a full page refresh. Details on how to implement an AJAX form are beyond the scope of this document, but you can consider using something like the jQuery Form Plugin to assist you (this sample code may be useful as well). You can also use a tool like the Advanced REST Client Chrome extension to do your testing.

Other than the endpoint, there are only two required aspects of how the form itself is built. First, it must use the encoding type multipart/form-data. And second, the uploaded image must be sent from an input with name="file".

The response is sent back to you in JSON format. Here is a portion of the results of a successful submission:

{
    size: 16532,
    deleted: 0,
    id: "1108775f-1bd5-f9b2-bd47-535e9f4509c0",
    name: "test1.jpg",
    mime_type: "image/jpg",
    width: 428,
    height: 428,
    date_created: "2014-04-28 18:34:54"
}

The id property is the most useful. You can store it in a field in a content set, and/or display the image using the _img processor as described on the Images & Files page.

So, returning to the team management widget above: how will we let the user select a logo? Here’s how we’ve done similar projects at Moboom:

  • Create a button called Update logo which opens up a modal lightbox on top of the page.
  • The lightbox has a new form with an Upload image button.
  • The lightbox form submits the image as described above, using AJAX.
  • When the form is successfully submitted, the image ID retrieved. Then the lightbox is closed and the image ID stored in a hidden field in the main form.
  • Optionally, the new image can be displayed in the main form.
  • When the main form is submitted, the data is stored into the content set using Moboom::updateContent(). The image ID is stored into a field in the content set along with all of the other user fields.

Given the complexity, we recommend taking this slowly, one step at a time, as you build up the knowledge needed to put the pieces together.