Panel field javascript click does not work after save

I’m working on panel field but I have a strange issue with javascript.

JS

function calle() {
  $( document ).ready(function() {
    $('.calle-table td').click(function() {
      console.log('test'); // Work, only before save
    });
    console.log('test'); // Work, always
  });
}
calle();

Everything works before save but the click function stop working after a save is made. There are no errors in the developer tools and the save is successful.

Any ideas why everything is working before save, but not after save?

UPDATE:

I removed the other fields from the blueprint. No luck.

I guess because the view is rendered again, but the javascript is not triggered again. So basically the .calle-table td is inserted after the click event was bound. Just a shot in the dark, as I have almost no experience with custom panel fields, but I often come across this problem when working with event handlers. Maybe have a look at other panel fields, to get an idea how others are doing it?

Yes, you are right. I looked into other plugins. Some added onclick directly on the inline element and others did a setTimeout to repeatable call the function again every second.

Right now I use the setTimeout version, but is it really the “correct” way?

Both ways are possible but rather hacky from by point of view, especially setTimeout is popular for doing such things quick’n’dirty (I tend to do those things too often by the way ;)). The best solution (as far as I know) would be to have a separate function which is triggered twice, after the document is ready and after the save was done (= the page was re-rendered). Usually this is done by special events, but as I said, I don’t really know how the panel fields are working, and therefore I also don’t know how to bind the events correctly.

Just as an example from sites using PJAX: here, PJAX triggers the custom event ‘pjax:complete’ after a successful ajax call, so you could bind the function to this event:

var pageReload = function(){
  // everything which should run after a new page call – as local bindings in the newly rendered area for example
};

$(document).ready(function(){
  // do other things like initializing PJAX
  // call pageReload on instant load
  pageReload();
});

// call pageReload after every complete ajax call with PJAX
$(document).on('pjax:complete', pageReload);

There should be some kind of similar event in Kirby which is triggered after the re-rendering of a page.

Looks like a really good solution. Too bad it does not work out of the box.

Is there a reason this is not built directly into the panel? @lukasbestle @distantnative @bastianallgeier Or are there other possibilities to get this work? If not, the app.load() function should fire an event (“panel:loaded” for example) which others could bind actions to (like binding click-handlers).

So far there’s no complete or loaded event, but we can easily add this. The correct way to handle this so far is to create a jquery field plugin.

A jQuery field plugin is easy to create. Here’s a boilerplate: https://gist.github.com/bastianallgeier/9398bbd72dcc782827a8

So this will take care of cleanly initiating the js code for every field instance and get the events right.

In your PHP field class, you can then activate the jQuery plugin for the field like this:

  public function element() {

    $element = parent::element();
    $element->data('field', 'myfield');

    return $element;

  }

What this does is to add a data-field attribute to the wrapping div around the field. The panel will automatically look for a jQuery plugin with the same name and initialize all events on every load.

In your jQuery plugin you can then do all the normal stuff you would do on document ready.

The field variable already from the boilerplate has the scope of the field div. So you can do finds within the div like this:

field.find('.calle-table td').on('click', function() {

});

I hope this helps.

5 Likes

Okay, I see. Nice and clean solution, one just has to know about that :wink:

1 Like

Yes it did. Worked for me. :slight_smile:

1 Like

@texnixe I often forget to close the issues when they are solved. Sorry about that! I’ll try to do better. :slight_smile:

No problem, usually, there is @lukasbestle to the rescue with cleaning up afterwards :joy: But it’s of course preferable, if people do it themselves when they are happy with the result …

2 Likes