Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Customising the CMS /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Can't Save ListBoxField With Multiple Vals?


Go to End


9 Posts   5795 Views

Avatar
_Vince

Community Member, 165 Posts

4 July 2009 at 2:52pm

Edited: 04/07/2009 8:53pm

Hi, I'm writing something that allows the CMS user to select products and bundle them together into kits.

The idea would be to have a flag on each product to say whether it's a kit of products or a single product. And if it's a kit of products, I'd like to save their ID numbers to an array (or an nested table)

I don't think I can save an array to MySql, so I'd like to have a text field where the product IDs are stored as a string of comma separated values.

class ProductsPage extends Page {

static $db = array(
.
.
.
'Is_Kit' => 'Boolean',
'Kit_Elements' => 'Text'
);

function getCMSFields() {
.
.
.
$fields->addFieldToTab("Root.Content.KitElements", new ListboxField(
$name = 'Kit_Elements',
$title ="Kit Elements",
$source = $productsMap,
'',
$size=4,
$multiple = true
)
);

The list, when displayed in the CMS, lets me select multiple values but as soon as I try to save, I get an "error while saving content" message.

I have also tried to put some code in onAfterWrite(), the idea being that, if the save is not automatic, then I could go back, grab the selected items from the list and write them to the DB column myself, but that doesn't work for me either.

    function onAfterWrite(){

        parent::onAfterWrite();
        
        $ProductList = null;
        $Product = DataObject::get_by_id("ProductsPage", $this->ID);

            while (list ($key, $val) = each ($this->Kit_Elements)) {
                $ProductList .= $val . ",";
            }
            $Product->Kit_Elements = $ProductList;

        $Product->write();

    }

What can I do? Or what am I doing wrong?

EDIT: There were a couple of typos which I fixed. But I still get the "Error saving content" message.

Avatar
Willr

Forum Moderator, 5523 Posts

4 July 2009 at 9:33pm

If you have firebug installed view the console tab (I think it will also show in the main firefox console tab). In this you can see the full error message SS sends (if not make sure your site is in devmode). That might give a clue

Avatar
_Vince

Community Member, 165 Posts

5 July 2009 at 12:25am

There's a LOT of stuff in there, but it also says

500 Warning: "Indirect modification of overloaded property ProductsPage::$Kit_Elements has no effect" at line 89...

Not sure that that means. If I don't bother with looking at the list and just hardcode a string, that works fine. So the modification would seem to have an effect.

But that's all in the processing in the onAfterWrite(). Do I really have to go through all this just to save multiple values on a ListboxField?

Avatar
_Vince

Community Member, 165 Posts

5 July 2009 at 9:51am


I changed things around a bit and now I get to save the values from the list. Thanks, Will! :)

    function onBeforeWrite(){
    
        $ProductList = null;
        
        for($i=0;$i<count($this->Kit_Elements);$i++){
            $ProductList .= $this->Kit_Elements[$i] . ",";
        }

        $this->Kit_Elements = substr($ProductList,0,strlen($ProductList) -1);
        
        return parent::onBeforeWrite();
    }

I get a column in the database with the product IDs, which is cool.

Now, my next question is, when the user goes on to view the page and maybe wants to change the items included in the kit, how do I tell the list to display with multiple values selected?

At the moment, if the text column in the DB contains the string "1,2,3", the list will display with "1" selected, but not "2" or "3". How can I get it to display with ALL the values in the database column selected? Ideally it wold look like

*product 1
*product 2
*product 3
product 4
product 5
product 6

where the "*" represent highlighted values.

I've tried hardcoding the values into the $value parameter of the ListBox but I think the commas "," separating the entries confuse it or something. Anyway, I seem to only get the first value highlighted.

Avatar
Willr

Forum Moderator, 5523 Posts

5 July 2009 at 10:55am

I believe ListboxField will at least take an array of values so maybe try exploding that 1,2,3 into an array and passing that into the constructor

<code>
$values = explode(",", $this->Kit_Elements);
$field = new ListBoxField($Kit_Elements, "Kit Elements", $products, $values);
</code>

Avatar
_Vince

Community Member, 165 Posts

5 July 2009 at 11:32am

Edited: 05/07/2009 11:33am

Well, I've tried that and got some mixed results.

First of all, I tried the explode but nothing changed. I only had ONE hightlighted value on the list, whatever value was in the database field before the first comma.

Then I tried feeding it an array manually as in:

$values = array(1,2,3);
$field = new ListboxField('Kit_Elements', "Kit Elements", $productsMap, $values,4, true);

and that didn't work EITHER until I removed the table definition

static $db = array(
'Product_Short_Description' => 'Varchar(20)',
.
.
.

from the php file. Then the list highlighted all the values that were in the array, but nothing was saved.

So the ListBox definitely takes an array in input but I'm apparently not generating a proper array from the database to pass to it.

It's a pity, because explode() seemed the way to go. :(

Avatar
Willr

Forum Moderator, 5523 Posts

5 July 2009 at 11:46am

perhaps you need to have an array with keys that match the values

array('1'=>'1', '2'=>'2','3'=> '3'); ?

Avatar
_Vince

Community Member, 165 Posts

5 July 2009 at 12:32pm

I've been trying that and no... that doesn't seem to work.

I can Debug::Show() the contents of the array created by the explode and they're fine but I just can't seem to herd them into the ListBox $values parameter.

Wonder what's wrong. :P Thanks so far though!

Go to Top