Forum

Custom Field Type from Odata - checkboxes

A site I'm working on is linked with another site (outside my control) which thankfully provides an Odata API for retrieving information. In my case, I'm pulling in lists of employees and publications; the end user needs to be able to select one or more people or publications from a list of checkboxes, and all the relevant information for the selected people/publications stored in the Perch DB for retrieval in a template.

Rachel already pointed me in the direction of creating custom field types for handling this data, and using Drew's Vimeo example I've been able to pull in raw JSON info into my field type admin template using CURL.

So far I've been able to output the list of people into a ul which contains a visible checkbox and name for each person. Their id, name, job title, profile picture URL and link to the other site's main page for that person are all stored in hidden fields.

What I can't figure out is how to actually pass the info to the back end for processing. None of the examples of custom field types I've seen use checkboxes, so I'm not sure how to use them to control what goes into the DB.

This is what my render_inputs looks like:

public function render_inputs($details=array())
{
    $id = $this->Tag->id();
    $input_id = $this->Tag->input_id();

    $val = '';

    if (isset($details[$id]) && $details[$id]!='') {
        $json = $details[$id];
        $val  = $json['selected']; 
    } else {
        $json = array();
    }

    $s = "";

    $details = $this->get_details(null); // gets the odata json, working fine


    $s     .= '<ul class="peopleScroller">';
    foreach($details as $person) {
        $s .= '<li>';
        $s .= $this->Form->checkbox($this->Tag->input_id(), $person['id'] . '_selected');
        $s .= $this->Form->hidden($this->Tag->input_id() . '_id', $person['id']);
        $s .= $this->Form->hidden($this->Tag->input_id() . '_name', $person['name']);
        $s .= $this->Form->hidden($this->Tag->input_id() . '_position', $person['position']);
        $s .= $this->Form->hidden($this->Tag->input_id() . '_portrait', $person['portrait']);
        $s .= $this->Form->hidden($this->Tag->input_id() . '_url', $person['url']);

        $s .= $person['name'];
        $s .= '</li>';
    }
    $s      .= '</ul>';

    return $s;
}

Does anyone have an idea how to do this? I think once I have once custom field type working, I should be able to manage the rest...

Mike Armstrong

Mike Armstrong 0 points

  • 6 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

You need to implement the get_raw method - again the Vimeo type is an ok example.

The first argument passed to this is an array of the posted data. You can look for your fields in that data, do any processing you need, and form the content into whatever shape you want to store it in. Then return that for storage.

I think I'm making a little progress. Due to the way the items will be used in the site (people may need to be re-ordered on a case-by-case basis), I've changed the input type from a checkbox to a select list, and have placed it in a repeater.

Here's my template code:

<perch:repeater id="hxd_people_list" label="HXD Team Members">
    <perch:before><ul class="list-plain list-people list-quarter"></perch:before>
    <perch:content id="hxd_person" type="hxd_person" label="Select HXD team member:" />
    <perch:after></ul></perch:after>
</perch:repeater>

In the admin interface, I'm outputting items like so:

public function render_inputs($details = array())
{
    $people = $this->get_details(null); // gets JSON from OData service

    $id     = $this->Tag->input_id();
    $class  = $this->Tag->class();

    $val = '';

    if (isset($details[$id]) && $details[$id]!='') {
        $json = $details[$id];
        $val  = $json['val']; 
    }


    $opts = array();
    if (PerchUtil::count($people) > 0) {

        foreach($people as $person) {
            $value = $person['id'] . '|' . $person['name'] . '|' . $person['position'] . '|' . $person['portrait'] . '|' . $person['url'];
            $name = $person['name'];

    $checked = $this->checked($details, $id, $value, $this->Tag->post_prefix());

    array_push($opts, array('label' => $name, 'value' => $value));

        }
    }
return $this->Form->select('hxd_person', $opts);
}

When processing the data, I explode the field value into an array for storage:

public function get_raw($post = false, $item = false)
{
    $store = array();

    $id = $this->Tag->id();

    if ($post===false) {
        $post = $_POST;
    }

    if (isset($post[$id])) {
        $this->raw_item = trim($post[$id]);
        $detailString = $this->raw_item;

        if ($detailString) {
            $details = explode("|", $detailString);

            if ($details) {
                $store['id'] = $details[0];
                $store['name'] = $details[1];
                $store['position'] = $details[2];
                $store['portrait'] = $details[3];
                $store['url'] = $details[4];
            }else{
                return false;
            }

            return $store;
        }
    }

    return false;
}

I can see that the data is being saved in the database's ItemSearch field, but the ItemJson is only holding the Perch _id field; nothing else is getting saved.

I'm obviously missing a step somewhere... any advice?

Drew McLellan

Drew McLellan 2638 points
Perch Support

I think you just need to test what values you've got at each step of the get_raw method - see where it's going wrong.

$id is posted back as hxd_person, but logging $post to screen returns the following:

Array ( [present] => 1 ) Array ( [present] => 1 ) 

As such, the processing of the values fails the isset check, as that's looking for $post[hdx_person] rather than $post[present]...

Changing the item to a regular template (not a repeater) and setting the region to allow multiple doesn't help much... $id is posted back correctly, but $post is now an empty array...

Drew McLellan

Drew McLellan 2638 points
Perch Support

You're hardcoding the field ID here:

return $this->Form->select('hxd_person', $opts);

Ah, that would be the problem!

I think I have everything working now.

Thanks Drew, once more you've gone above & beyond!