Jump to content

Wrong before and after values for repeaters on $page->isChanged


gebeer
 Share

Recommended Posts

Hello,

To compare repeater items when someone added or removed items to/from the repeater, I use this hook

wire()->addHookAfter('Pages::saveReady', function($event) {

	$page = $event->arguments[0];

	if($page->isChanged('repeater')) {
		//get page before changes : https://processwire.com/talk/topic/9734-determine-old-vs-new-value-of-field-when-saving/?do=findComment&comment=106166
		$oldPage = $this->wire('pages')->getById($page->id, array(
				'cache' => false, // don't let it write to cache
				'getFromCache' => false, // don't let it read from cache
				'getOne' => true, // return a Page instead of a PageArray
			));

		bardump("new count: {$page->repeater->count}");
		bardump("old count: {$oldPage->repeater->count}");
	}

});

When I add a repeater item, both counts are identical. But they shouldn't.
When I remove a repeater item, the counts come out correct.

I verified this behavior on a blank PW 3.0.62 install. So I think it is a bug.

Can someone please check if they find the same behavior? Thank you.

I also tried it with this hook

wire()->addHookAfter('Page(template=basic-page)::changed(repeater)', function($event) {
    
    // old value
	bardump($event->arguments[1]->count);
    // new value
	bardump($event->arguments[2]->count);

});

Same outcome.

For the second hook to fire, you need to adjust line 1005 in wire/core/Wire.php to read

				if(($hooks && $hooks->isHooked('changed()')) || !$hooks) {

because of this bug.

Link to comment
Share on other sites

I think this is because as soon as you click "Add New" in a repeater inputfield a new as-yet-unpublished page is added to the repeater. So when you get the "old" page after saveReady this unpublished repeater item already exists and is included in count().

Try this:

wire()->addHookAfter('Pages::saveReady', function($event) {

    $page = $event->arguments[0];

    if($page->isChanged('repeater')) {
        $old_repeater_value = $this->pages->getById($page->id, array(
            'cache' => false,
            'getFromCache' => false,
            'getOne' => true,
        ))->repeater->not('published=0'); // exclude as-yet-unpublished items

        bd($page->repeater->count, 'new count');
        bd($old_repeater_value->count, 'old count');
    }

});

 

  • Like 2
Link to comment
Share on other sites

@Robin S spot on! Thank you very much. This is working. Except for I had to exit the hook for template repeater_repeater. Otherwise I got an error "Call to a member function not() on null" for the "->repeater->not('published=0')" part of your code.

The working version now reads

wire()->addHookAfter('Pages::saveReady', function($event) {

    $page = $event->arguments[0];

    if($page->template == 'repeater_repeater') return;
    
    if($page->isChanged('repeater')) {
        $old_repeater_value = $this->pages->getById($page->id, array(
            'cache' => false,
            'getFromCache' => false,
            'getOne' => true,
        ))->repeater->not('published=0'); // exclude as-yet-unpublished items

        bd($page->repeater->count, 'new count');
        bd($old_repeater_value->count, 'old count');
    }

});

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...