naja-js/naja

Working with snippet containers

dakur opened this issue · 4 comments

dakur commented

From quick look into source code it seems that Naja snippet rerendering is built on principle "let's see what IDs came from server, check if they exist in DOM and do an update". That's fine until you have static snippet container with dynamic snippets inside and some of them should be removed when AJAX request is finished.

Let's take an example of page with feedbacks - you know...
image

When you hit the toggle button, request is sent to backend and the selected feedback is marked as resolved. Once resolved, it should be hidden from the unresolved feedback list. Nette invalidates controls and list with only one feedback is returned, but Naja only updates this one returned element and the rest is untouched.

I'd say it should be aware of dynamic snippets and their dynamics somehow.

The implementation in Naja is valid. Nette snippets itself don't support removing of particular snippets/dynamic snippets.

You can either

  • add some info to a payload which elements should be removed and write custom JS (maybe as a naja extension)
  • or you can wrap your snippet with another snippet and redraw this one
dakur commented

or you can wrap your snippet with another snippet and redraw this one

That's what I did. I did following:

latte:

<div n:snippet="feedback">
  <div n:foreach="$feedbacks as $feedback" n:snippet="feedback-{$feedback->id}">
    {$feedback->text}{* just to have something here *}
  </div>
</div>

presenter:

public function render()
{
  $feedbacks = $this->feedbackFacade->getUnresolved();
  $this->getTemplate()->add('feedbacks', $feedbacks);
}

The point is that when the render method is called on page load, it returns an array of two items. But when it is called after AJAX request is handled (on invalidate), it contains only one item, because the second item has been already marked as resolved. And because of the mechanism described above, the content is not updated "correctly". I write "correctly" because this issue is not really a bug, it is more about how whole extension is thought up.

and are you sure you need dynamic snippets? usage for dynamic snippets is that you have a list of items and you want to redraw just one of them. then you send to the template only that and rest of items stays untouched.

if you remove n:snippet="feedback-{$feedback->id}" then it will behave like "normal" snippets and feedback snippet will be send to a browser as a single item.

Or if you really need dynamic snippets then add some {snippet feedbackWrapper} and invalidate this one.

you can check my talk about snippets https://www.youtube.com/watch?v=CoXJnOCRQ70 (czech only)

dakur commented

Yes, I need dynamic snippets as I want to hide a single feedback with smooth animation once resolved. But I overlooked your first suggestion - add some info to a payload which elements should be removed and write custom JS - that's good enough solution. Thank you.