Unable to repeat DataWriter actions after ajax return

Myke623

Well-known member
I have a list of Items (stored in one table). Each Item can optionally have a bunch of related Sub-Items (stored in another table). Editing the Items, and any Sub-Items, is done via a FormOverlay, and the updated result is returned via ajax.

This all works as expected, but only for the first time.

Subsequent attempts to edit the same Item 'fail'. By 'fail' I mean they don't work, and no errors are returned.

If I reload the page, however, I can edit the Item and its Sub-Items again.

The actionSave() method this occurs in is basically structured as follows:

PHP:
public function actionSave()
{
    // Get inputs
    $item_id = $this->_input->filterSingle('com_id', XenForo_Input::UINT);
    // ... etc
  
    // Create the data writer
    $dw = XenForo_DataWriter::create('Items_DataWriter_Item');

    // Set the existing data
    $dw->setExistingData($item_id);
  
    // Set the Item data
    $dw->bulkSet(
        array(
                'name'        => $input['name'],
        )
    );
  
    // And save
    $dw->save();
  
    // Now with the main item saved, add sub-items if selected...
    if (isset($subitems_add))
    {
        // Format: Array of key-values for sub-item names
        //   e.g.: $subitems_add = array([0] => 'foo', [1] => 'bar', ...)
        foreach ($subitems_add as $subitem_name)
        {
            $dw = XenForo_DataWriter::create('Items_DataWriter_SubItem');
            $dw->bulkSet(
                array(
                        'item_id'  => $item_id,
                        'name'     => $subitem_name,
                )
            );
            $dw->save();
        }
    }
  
    // and/or delete sub-items if applicable...
    if (isset($subitems_del))
    {
        // Format: Array of key-values sub-item IDs
        //   e.g.: $subitems_del = array([0] => 1, [1] => 2, ...)
        foreach ($subitems_del as $subitem_id)
        {
            $dw = XenForo_DataWriter::create('Items_DataWriter_SubItem');
            $dw->setExistingData($subitem_id);
            $dw->delete();
        }
    }

    // Only run this code if the action has been loaded via XenForo.ajax()
    if ($this->_noRedirect())
    {
        // Get the item list
        $itemList = $this->_getItemListModel()->getById($item_id);
                  
        $viewParams = array(
                'item'             => $itemList[$item_id],
        );
          
        return $this->responseView('Items_ViewPublic_Item', 'items_list_item', $viewParams);
  
    }
    else
    {
        return $this->responseRedirect(
                XenForo_ControllerResponse_Redirect::SUCCESS,
                XenForo_Link::buildPublicLink('items/list'),
                "Item Updated"
        );
    }
}

Note: the code above is heavily generalised, but I believe I've shown the relevant components -- namely, the use of the DataWriter within foreach loops, along with the ajax return.

Any ideas as to why I need to reload the page each time, before I can successfully edit the same item again?
 
Last edited:
Never mind this thread. Has nothing to do with the DataWriter, and everything to do with my ajax/js. I'll post a separate thread about it.
 
Don't you hate it when you search for a particular development issue you're having, and you find a thread that describes the exact same problem you're having, but there's no answer? :) Well, in order to prevent that from happening I just thought I'd close the loop on this thread!

The problem I experienced had nothing to do with multiple DataWriter calls. In other words, multiple DataWriter calls work perfectly fine within, say, a foreach loop. You just need to remember to create the DataWriter on each iteration.

As it turned out, the problem I had was related to the form data being submitted not being updated correctly (and hence, my DataWriter effectively had nothing to do). The reason the form data wasn't being updated correctly was due to a deficiency in my javascript code, which you can read about in the jQuery setting value on hidden input thread, along with its resolution.
 
Top Bottom