<p>Use that as your controller, this is the craft default controller actionSaveEntry that you use right now with a few changes. You can access it in Javascript when you use action: "pluginHandle/entry/saveEntry".</p>

<pre><code>namespace Craft;

class EntryController extends BaseController
{

    /**
     * @var    bool|array Allows anonymous access to this controller's actions.
     * @access protected
     */
    protected $allowAnonymous = array('actionSaveEntry');


    /**
     * Saves an entry.
     *
     * @return null
     */
    public function actionSaveEntry()
    {
        // craft default things.. this is actually the exact same function
        // like you call at the moment, it does the same..
        // just go to the part where I have the !Important! note
        $this-&gt;requirePostRequest();

        $entry = $this-&gt;_getEntryModel();

        // Permission enforcement
        $this-&gt;enforceEditEntryPermissions($entry);
        $userSessionService = craft()-&gt;userSession;
        $currentUser = $userSessionService-&gt;getUser();

        if ($entry-&gt;id) {
            // Is this another user's entry (and it's not a Single)?
            if (
                $entry-&gt;authorId != $currentUser-&gt;id &amp;&amp;
                $entry-&gt;getSection()-&gt;type != SectionType::Single
            ) {
                if ($entry-&gt;enabled) {
                    // Make sure they have permission to make live changes to those
                    $userSessionService-&gt;requirePermission('publishPeerEntries:' . $entry-&gt;sectionId);
                }
            }
        }

        // Populate the entry with post data
        $this-&gt;_populateEntryModel($entry);

        // Even more permission enforcement
        if ($entry-&gt;enabled) {
            if ($entry-&gt;id) {
                $userSessionService-&gt;requirePermission('publishEntries:' . $entry-&gt;sectionId);
            } else if (!$currentUser-&gt;can('publishEntries:' . $entry-&gt;sectionId)) {
                $entry-&gt;enabled = false;
            }
        }

        // Save the entry (finally!)
        // !Important! so this is where your action starts
        if (craft()-&gt;entries-&gt;saveEntry($entry)) {
            $return['success'] = true;
            $return['id'] = $entry-&gt;id;
            $return['title'] = $entry-&gt;title;

            // after saving the entry you can render your template
            // the documentation can be found here https://craftcms.com/docs/plugins/templates
            // just read this site and you'll know what to do.. 
            // this allows you to render your "comments" template like when you 
            // visit the page the first initially
            // you'll just do $("#idOfYourCommentsContainer").append(ajaxResponse['html']);
            // and thats it^^ 
            // in the template you have access to the variables $entry =&gt; the new entry
            // and the user currently.. if you need something else, feel free to ask
            $return['html'] = $this-&gt;renderTemplate('/path/to/template', array(
                'entry' =&gt; $entry,
                'user' =&gt; $entry-&gt;getAuthor()
            ));

            $return['authorUsername'] = $entry-&gt;getAuthor()-&gt;username;
            $return['dateCreated'] = DateTimeHelper::toIso8601($entry-&gt;dateCreated);
            $return['dateUpdated'] = DateTimeHelper::toIso8601($entry-&gt;dateUpdated);
            $return['postDate'] = ($entry-&gt;postDate ? DateTimeHelper::toIso8601($entry-&gt;postDate) : null);

            $this-&gt;returnJson($return);
        } else {
            if (craft()-&gt;request-&gt;isAjaxRequest()) {
                $this-&gt;returnJson(array(
                    'errors' =&gt; $entry-&gt;getErrors(),
                    'success' =&gt; false
                ));
            }
        }
    }
}
</code></pre>

<p>If there is an error you get the array with all "mistakes" and error messages. For example if you define the field "headline" as required and the user didn't insert something in the "headline" field your response will be</p>

<pre><code>reponse = [
    "error" =&gt; [
        'headline'  =&gt; [
            'The Headline field is required //or something like that...'
        ]
    ]
];
</code></pre>

<p>You could select the <code>headline</code> field by name or class with javascript and append the error message as well</p>

CC BY-SA 3.0
2017-10-25T20:29:33.673Z
Robin this looks great! And is making (some!) sense, I'm going to have a go at getting this in this evening, will report back shortly.
shorn
CC BY-SA 3.0
2017-10-25T20:36:43.367Z
Ahh I just noticed.. You'll have to copy the `_getEntryModel()` and the `_populateEntryModel()` from `craft/app/controllers/entrieController` as well I forgot that. Craft is (mostly) relativ logical and fun to work with (as soon as you understand it). The most common way to go is reading the craft code how they did something and do the same. If you want, I can add you on Skype and answer more of your questions that don't belong here
Robin Schambach
CC BY-SA 3.0
2017-10-25T22:44:59.320Z
Been working through this. No luck as of yet, getting 500 error, but then saw comment to include the other two functions. Have done that but still getting a 500 error `syntax error, unexpected '$this' (T_VARIABLE), expecting function (T_FUNCTION)` - having a look now to see if I can spot anything obvious.
shorn
CC BY-SA 3.0
2017-10-25T22:53:03.460Z
The one before was bad copy and pasting. I think! Current error is on `...behaviors do not have a method or closure named enforceEditEntryPermissions`
shorn
CC BY-SA 3.0
2017-10-25T22:58:28.447Z
OK, so copied the `enforceEditEntryPermissions ` into it as well and it seems to be working. Haven't fleshed out the template yet, but I'm logging the test div from it! :)
shorn
CC BY-SA 3.0
2017-10-25T23:02:15.497Z
Yes sry you need that method too... I forgot about that, you can just use `class EntryController extends EntriesController` instead of `class EntryController extends BaseController` in order to get access to those methods as well. For your template. Copy the code you have in your normal template to the new one. Put it in your plugins `/templates` path and follow the rules from the documents. If you use any special variables (other than user and entry) let me know and I'll provide them.
Robin Schambach
CC BY-SA 3.0
2017-10-25T23:22:46.817Z
OK, no worries. So it seems to all be working nicely. Just added in my comment template, updated the variables where needed and it seems to be running nicely. Comment loads in nice just after hitting save. On minor issue is that the comment has the date displayed below it. Sometimes this doesnt show when the comment is first saved and loads in. I run the `time_diff` filter on it, so my guess is that theres not enough time elapsed from saving it to displaying it perhaps?
shorn
CC BY-SA 3.0
2017-10-25T23:32:03.177Z
Yes. Since this filter is provided by a custom plugin (as far as I know) and the time between saving and rendering it should be only a few milliseconds the result could be rounded to null. You could check `{% if variable|time_diff %} variable|time_diff {% else %} a few seconds ago {% endif %}` or something like that
Robin Schambach
CC BY-SA 3.0
2017-10-25T23:39:24.920Z
Yea, that's what I'm doing. Might have a go at handling that in the twig extension though, especially now that I'm on a roll with plugins! :) Man thanks for your help. Wouldn't have got this working otherwise. Feels like a nice jump forward. I'll be onto the email part next. I owe you a beer!
shorn
CC BY-SA 3.0
2017-10-25T19:33:09.957Z
2017-10-25T19:50:21.610Z
2017-10-25T19:50:21.610Z
Robin Schambach
<p>What you could do is to use the <code>entries.onSaveEntry</code> to override the ajax response of the EntriesController for your specific entry section.</p>

<p>The <code>actionSaveEntry</code> from the EntriesController save the entry and immediately send back an ajax response so it is pretty harmless to do that. And if there is an error during the saving your code won't be called so Craft will follow its normal flow.</p>

<pre><code>craft()-&gt;on('entries.onSaveEntry', function (Event $event) {
    $entry = $event-&gt;params['entry'];
    $section = $entry-&gt;section-&gt;handle;

    if ($section == 'Your specific section') {

       if (craft()-&gt;request-&gt;isAjaxRequest() &amp;&amp; !craft()-&gt;request-&gt;isCpRequest()) {
          $return['success']   = true;
          $return['id']        = $entry-&gt;id;
          $return['title']     = $entry-&gt;title;
          $return['comment']     = $entry-&gt;comment; // whatever you want

          $return['authorUsername']      = $entry-&gt;getAuthor()-&gt;username;
          $return['dateCreated'] = DateTimeHelper::toIso8601($entry-&gt;dateCreated);
          $return['dateUpdated'] = DateTimeHelper::toIso8601($entry-&gt;dateUpdated);
          $return['postDate']    = ($entry-&gt;postDate ? DateTimeHelper::toIso8601($entry-&gt;postDate) : null);

          craft()-&gt;controller-&gt;returnJson($return);
        }
    }
});
</code></pre>

<p>Hope this helps</p>

CC BY-SA 3.0
2018-04-24T15:43:11.763Z
2018-04-24T15:43:11.763Z
Thomas Joeisseint
<p>I’ve created a very simple comments system whereby comments are set us a channel, with each (comment )entry related to a main entry from another section. Works fine. I’ve set up editing and deleting the comment via Ajax, but I’m stuck on saving it.
I’ve got the form submitting successfully via ajax, but I want to be able to display it immediately after it is saved/posted.
The successful response I get gives me the author username, entry id, date etc, but not the actual comment field. I also need to display additional user details.</p>

<p>I’m not quite sure on best way to tackle this. Just looking for a pointer in the right direction. Cheers!</p>

CC BY-SA 3.0
2017-10-25T19:14:46.883Z
The best - and usually most common - way to achieve this is by rendering the needed html in your controller where you prepare your database entry. If you don't use a custom controller, just give me your action url (the route you have in your ajax) and I'll create a controller/plugin for you that does the job tomorrow. Btw were you able to understand the last code I gave you?
Robin Schambach
CC BY-SA 3.0
2017-10-25T19:18:23.150Z
Hi Robin, thanks. I don't use a custom controller at all. It just going to standard `entries/saveEntry` (i think!). I do for the most part understand the other code, it's linked to this :) I wanted to get this saving part wrapped up before testing the other out. Thanks!
shorn
<entry><ajax>
Saving new entry via Ajax then immediately showing it
# Saving new entry via Ajax then immediately showing it

(Asked by: username_0 on 2017-10-25)

I’ve created a very simple comments system whereby comments are set us a channel, with each (comment )entry related to a main entry from another section. Works fine. I’ve set up editing and deleting the comment via Ajax, but I’m stuck on saving it.
I’ve got the form submitting successfully via ajax, but I want to be able to display it immediately after it is saved/posted.
The successful response I get gives me the author username, entry id, date etc, but not the actual comment field. I also need to display additional user details.

I’m not quite sure on best way to tackle this. Just looking for a pointer in the right direction. Cheers!

**Tags:** entry, ajax

> **Comments:**
> **username_1**: The best - and usually most common - way to achieve this is by rendering the needed html in your controller where you prepare your database entry. If you don't use a custom controller, just give me your action url (the route you have in your ajax) and I'll create a controller/plugin for you that does the job tomorrow. Btw were you able to understand the last code I gave you?  
> **username_0**: Hi Robin, thanks. I don't use a custom controller at all. It just going to standard `entries/saveEntry` (i think!). I do for the most part understand the other code, it's linked to this :) I wanted to get this saving part wrapped up before testing the other out. Thanks!  

---

## 2 answers

### Answer by username_1 on 2017-10-25. Score: 2 | Accepted answer

Use that as your controller, this is the craft default controller actionSaveEntry that you use right now with a few changes. You can access it in Javascript when you use action: "pluginHandle/entry/saveEntry".
namespace Craft;

class EntryController extends BaseController
{

    /**
     * @var    bool|array Allows anonymous access to this controller's actions.
     * @access protected
     */
    protected $allowAnonymous = array('actionSaveEntry');


    /**
     * Saves an entry.
     *
     * @return null
     */
    public function actionSaveEntry()
    {
        // craft default things.. this is actually the exact same function
        // like you call at the moment, it does the same..
        // just go to the part where I have the !Important! note
        $this->requirePostRequest();

        $entry = $this->_getEntryModel();

        // Permission enforcement
        $this->enforceEditEntryPermissions($entry);
        $userSessionService = craft()->userSession;
        $currentUser = $userSessionService->getUser();

        if ($entry->id) {
            // Is this another user's entry (and it's not a Single)?
            if (
                $entry->authorId != $currentUser->id &&
                $entry->getSection()->type != SectionType::Single
            ) {
                if ($entry->enabled) {
                    // Make sure they have permission to make live changes to those
                    $userSessionService->requirePermission('publishPeerEntries:' . $entry->sectionId);
                }
            }
        }

        // Populate the entry with post data
        $this->_populateEntryModel($entry);

        // Even more permission enforcement
        if ($entry->enabled) {
            if ($entry->id) {
                $userSessionService->requirePermission('publishEntries:' . $entry->sectionId);
            } else if (!$currentUser->can('publishEntries:' . $entry->sectionId)) {
                $entry->enabled = false;
            }
        }

        // Save the entry (finally!)
        // !Important! so this is where your action starts
        if (craft()->entries->saveEntry($entry)) {
            $return['success'] = true;
            $return['id'] = $entry->id;
            $return['title'] = $entry->title;

            // after saving the entry you can render your template
            // the documentation can be found here https://craftcms.com/docs/plugins/templates
            // just read this site and you'll know what to do.. 
            // this allows you to render your "comments" template like when you 
            // visit the page the first initially
            // you'll just do $("#idOfYourCommentsContainer").append(ajaxResponse['html']);
            // and thats it^^ 
            // in the template you have access to the variables $entry => the new entry
            // and the user currently.. if you need something else, feel free to ask
            $return['html'] = $this->renderTemplate('/path/to/template', array(
                'entry' => $entry,
                'user' => $entry->getAuthor()
            ));

            $return['authorUsername'] = $entry->getAuthor()->username;
            $return['dateCreated'] = DateTimeHelper::toIso8601($entry->dateCreated);
            $return['dateUpdated'] = DateTimeHelper::toIso8601($entry->dateUpdated);
            $return['postDate'] = ($entry->postDate ? DateTimeHelper::toIso8601($entry->postDate) : null);

            $this->returnJson($return);
        } else {
            if (craft()->request->isAjaxRequest()) {
                $this->returnJson(array(
                    'errors' => $entry->getErrors(),
                    'success' => false
                ));
            }
        }
    }
}

If there is an error you get the array with all "mistakes" and error messages. For example if you define the field "headline" as required and the user didn't insert something in the "headline" field your response will be
reponse = [
    "error" => [
        'headline'  => [
            'The Headline field is required //or something like that...'
        ]
    ]
];

You could select the headline field by name or class with javascript and append the error message as well

> **Comments:**
> **username_0**: Robin this looks great! And is making (some!) sense, I'm going to have a go at getting this in this evening, will report back shortly.  
> **username_1**: Ahh I just noticed.. You'll have to copy the `_getEntryModel()` and the `_populateEntryModel()` from `craft/app/controllers/entrieController` as well I forgot that. Craft is (mostly) relativ logical and fun to work with (as soon as you understand it). The most common way to go is reading the craft code how they did something and do the same. If you want, I can add you on Skype and answer more of your questions that don't belong here  
> **username_0**: Been working through this. No luck as of yet, getting 500 error, but then saw comment to include the other two functions. Have done that but still getting a 500 error `syntax error, unexpected '$this' (T_VARIABLE), expecting function (T_FUNCTION)` - having a look now to see if I can spot anything obvious.  
> **username_0**: The one before was bad copy and pasting. I think! Current error is on `...behaviors do not have a method or closure named enforceEditEntryPermissions`  
> **username_0**: OK, so copied the `enforceEditEntryPermissions ` into it as well and it seems to be working. Haven't fleshed out the template yet, but I'm logging the test div from it! :)  
> **username_1**: Yes sry you need that method too... I forgot about that, you can just use `class EntryController extends EntriesController` instead of `class EntryController extends BaseController` in order to get access to those methods as well. For your template. Copy the code you have in your normal template to the new one. Put it in your plugins `/templates` path and follow the rules from the documents. If you use any special variables (other than user and entry) let me know and I'll provide them.  
> **username_0**: OK, no worries. So it seems to all be working nicely. Just added in my comment template, updated the variables where needed and it seems to be running nicely. Comment loads in nice just after hitting save. On minor issue is that the comment has the date displayed below it. Sometimes this doesnt show when the comment is first saved and loads in. I run the `time_diff` filter on it, so my guess is that theres not enough time elapsed from saving it to displaying it perhaps?  
> **username_1**: Yes. Since this filter is provided by a custom plugin (as far as I know) and the time between saving and rendering it should be only a few milliseconds the result could be rounded to null. You could check `{% if variable|time_diff %} variable|time_diff {% else %} a few seconds ago {% endif %}` or something like that  
> **username_0**: Yea, that's what I'm doing. Might have a go at handling that in the twig extension though, especially now that I'm on a roll with plugins! :) Man thanks for your help. Wouldn't have got this working otherwise. Feels like a nice jump forward. I'll be onto the email part next. I owe you a beer!  

---

### Answer by username_2 on 2018-04-24. Score: 0

What you could do is to use the entries.onSaveEntry to override the ajax response of the EntriesController for your specific entry section.
The actionSaveEntry from the EntriesController save the entry and immediately send back an ajax response so it is pretty harmless to do that. And if there is an error during the saving your code won't be called so Craft will follow its normal flow.
craft()->on('entries.onSaveEntry', function (Event $event) {
    $entry = $event->params['entry'];
    $section = $entry->section->handle;

    if ($section == 'Your specific section') {

       if (craft()->request->isAjaxRequest() && !craft()->request->isCpRequest()) {
          $return['success']   = true;
          $return['id']        = $entry->id;
          $return['title']     = $entry->title;
          $return['comment']     = $entry->comment; // whatever you want

          $return['authorUsername']      = $entry->getAuthor()->username;
          $return['dateCreated'] = DateTimeHelper::toIso8601($entry->dateCreated);
          $return['dateUpdated'] = DateTimeHelper::toIso8601($entry->dateUpdated);
          $return['postDate']    = ($entry->postDate ? DateTimeHelper::toIso8601($entry->postDate) : null);

          craft()->controller->returnJson($return);
        }
    }
});

Hope this helps


---

