<p>Have you tried the <a href="https://docs.craftcms.com/api/v3/craft-base-element.html#method-isfielddirty" rel="nofollow noreferrer"><code>$element-&gt;isFieldDirty()</code></a> method, or checking through the <a href="https://docs.craftcms.com/api/v3/craft-base-element.html#dirtyfields" rel="nofollow noreferrer"><code>$element-&gt;dirtyFields</code></a> array for your asset field, rather than checking revision dates?</p>
<p>There may be a good reason why you're not using those, but I thought I'd suggest it in case you hadn't considered it.</p>

CC BY-SA 4.0
2021-05-05T19:06:34.007Z
I appreciate the suggestion, and this does seem to consistently tell me that the asset field has changed. But we need details about the asset itself which I don't think we can get via dirtyFields.
plaintxt
CC BY-SA 4.0
2021-05-05T20:38:31.783Z
I decided to flag this as the correct answer because $element-dirtyFields does reliably tell me whether the Custom Image has been updated during the save cycle. I can then use $entry->customImage->one(), which will either return null (image removed) or an AssetQuery that I can use to get the detailed info we need. Thanks!
plaintxt
CC BY-SA 4.0
2022-02-17T17:56:20.563Z
Sorry to hijack, `isFieldDirty` only works for custom fields, is there an equivalent for `title` or `status` do you know? Thanks
iamkeir
CC BY-SA 4.0
2022-02-17T18:04:12.843Z
Answered my own question, yes, `$element->isAttributeDirty('title')`... :)
iamkeir
CC BY-SA 4.0
2022-02-18T13:38:03.940Z
Gah...`isAttributeDirty` and `isFieldDirty` return inconsistent/inaccurate responses when used with `EVENT_ON_SAVE`... https://craftcms.stackexchange.com/questions/39066/check-if-element-status-has-changed-on-event-before-save
iamkeir
CC BY-SA 4.0
2021-05-05T10:25:20.143Z
2021-05-05T10:25:20.143Z
Wallace
<p>We need to send a notification email when an entry's asset field, Custom Image, has been updated on entry save. We're able to do this consistently for text fields but I'm having trouble doing the same for an asset field.</p>
<pre><code>// Use statements etc

...

// Register the event handler
Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, [$this, 'handleAfterSave']);

...

public function handleAfterSave(ModelEvent $event): void
{
    $entry = $event-&gt;sender;
    $revisions = Entry::find()-&gt;revisionOf($entry)-&gt;status(null)-&gt;orderBy('revisionId DESC')-&gt;all();
    $lastRevision = Craft::$app-&gt;getElements()-&gt;getElementById($revisions[1]-&gt;id);

    $fields = Craft::$app-&gt;getFields();
    
    // text fields
    $notificationHandles = [
        'textField1',
        'textField2',
    ];
    $updatedFields = array_map(
        fn ($h) =&gt; [
            'fieldName' =&gt; $fields-&gt;getFieldByHandle($h)-&gt;name,
            'oldValue' =&gt; $lastRevision[$h],
            'newValue' =&gt; $entry[$h],
        ],
        // Only need to show field if different from last revision
        array_filter($notificationHandles, fn ($h) =&gt; $lastRevision[$h] !== $entry[$h])
    );
    
    if (count($updatedFields) &gt; 0) {
        self::$notifications-&gt;notifyUpdated($entry, $updatedFields);
    }
}
</code></pre>
<p>The above works for text fields. However, when adapting for an asset field, it appears that <code>$lastRevision[$h]</code> is not immediately updated.</p>
<p>If we have an entry with an empty Custom Image asset field:</p>
<ol>
<li>Assign an image to Custom Image</li>
<li>Save</li>
<li>Email is sent</li>
<li>Return to the entry</li>
<li>Remove the asset from Custom Image</li>
<li>Save</li>
<li>No email is sent</li>
</ol>
<p>To put it another way, if I have an entry with an empty Custom Image field:</p>
<ol>
<li>Assign an image to Custom Image</li>
<li>Save</li>
<li>Email is sent</li>
<li>Return to the entry</li>
<li>Remove the asset from Custom Image</li>
<li>Save, but dump <code>$lastRevision</code> using <code>EVENT_AFTER_SAVE</code></li>
<li>We can see that <code>customImage</code> is still <code>null</code>, where I would expect it to show the previously attached image (an AssetQuery etc)</li>
<li>No email is sent because both <code>$lastRevision['customImage']</code> and <code>$entry['customImage']</code> are <code>null</code>.</li>
</ol>
<p>Thanks!</p>

<craft3><assets><events>
How would I detect whether an entry's asset field has been updated on save?
# How would I detect whether an entry's asset field has been updated on save?

(Asked by: username_0 on 2021-05-04)

We need to send a notification email when an entry's asset field, Custom Image, has been updated on entry save. We're able to do this consistently for text fields but I'm having trouble doing the same for an asset field.
// Use statements etc

...

// Register the event handler
Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, [$this, 'handleAfterSave']);

...

public function handleAfterSave(ModelEvent $event): void
{
    $entry = $event->sender;
    $revisions = Entry::find()->revisionOf($entry)->status(null)->orderBy('revisionId DESC')->all();
    $lastRevision = Craft::$app->getElements()->getElementById($revisions[1]->id);

    $fields = Craft::$app->getFields();
    
    // text fields
    $notificationHandles = [
        'textField1',
        'textField2',
    ];
    $updatedFields = array_map(
        fn ($h) => [
            'fieldName' => $fields->getFieldByHandle($h)->name,
            'oldValue' => $lastRevision[$h],
            'newValue' => $entry[$h],
        ],
        // Only need to show field if different from last revision
        array_filter($notificationHandles, fn ($h) => $lastRevision[$h] !== $entry[$h])
    );
    
    if (count($updatedFields) > 0) {
        self::$notifications->notifyUpdated($entry, $updatedFields);
    }
}

The above works for text fields. However, when adapting for an asset field, it appears that $lastRevision[$h] is not immediately updated.
If we have an entry with an empty Custom Image asset field:

Assign an image to Custom Image
Save
Email is sent
Return to the entry
Remove the asset from Custom Image
Save
No email is sent

To put it another way, if I have an entry with an empty Custom Image field:

Assign an image to Custom Image
Save
Email is sent
Return to the entry
Remove the asset from Custom Image
Save, but dump $lastRevision using EVENT_AFTER_SAVE
We can see that customImage is still null, where I would expect it to show the previously attached image (an AssetQuery etc)
No email is sent because both $lastRevision['customImage'] and $entry['customImage'] are null.

Thanks!

**Tags:** craft3, assets, events


---

## 1 answers

### Answer by username_1 on 2021-05-05. Score: 2 | Accepted answer

Have you tried the [`$element->isFieldDirty()`](https://docs.craftcms.com/api/v3/craft-base-element.html#method-isfielddirty) method, or checking through the [`$element->dirtyFields`](https://docs.craftcms.com/api/v3/craft-base-element.html#dirtyfields) array for your asset field, rather than checking revision dates?

There may be a good reason why you're not using those, but I thought I'd suggest it in case you hadn't considered it.

> **Comments:**
> **username_0**: I appreciate the suggestion, and this does seem to consistently tell me that the asset field has changed. But we need details about the asset itself which I don't think we can get via dirtyFields.  
> **username_0**: I decided to flag this as the correct answer because $element-dirtyFields does reliably tell me whether the Custom Image has been updated during the save cycle. I can then use $entry->customImage->one(), which will either return null (image removed) or an AssetQuery that I can use to get the detailed info we need. Thanks!  
> **username_2**: Sorry to hijack, `isFieldDirty` only works for custom fields, is there an equivalent for `title` or `status` do you know? Thanks  
> **username_2**: Answered my own question, yes, `$element->isAttributeDirty('title')`... :)  
> **username_2**: Gah...`isAttributeDirty` and `isFieldDirty` return inconsistent/inaccurate responses when used with `EVENT_ON_SAVE`... https://craftcms.stackexchange.com/questions/39066/check-if-element-status-has-changed-on-event-before-save  

---

