D8: refresh JS modulhoz

makgab képe

Üdv!
Van egy saját modul, ami SQL SELECT parancs eredményét jeleníti meg html table-ben.
src/Controller/MyModuleController.php:

   // ...
    $rows = [];
    foreach ($result as $row) {
      $rows[] = ['data' => (array) $row];
    }
 
    // Build the table
    $build = [
      '#markup' => '<p>' . t('The data from server.') . '</p>',
    ];
    $build['mymodule_table'] = [
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    ];
    // add lib, js
    $build['mymodule_table']['#attached']['library'][] = 'mymodule/mymodule.query.data';
 
    return $build;
  }

mymodule.libraries.yml:
mymodule.query.data:
  version: 1.x
  header: true
  js:
    js/my.js: {}

A my.js tartalma egyelőre teszt jelleggel:
alert("JS works!");

mymodule.routing.yml:

mymodule.query.data:
  path: '/mymodule/query/data'
  defaults:
    _controller: 'Drupal\mymodule\Controller\MyModuleController::query_data'
    _title: 'MyModule Query Data'
  requirements:
    _permission: 'access content'

De nem adja hozzá az routing-hoz (mymodule.query.data) a my.js-t.
Mi kell még hozzá?

(D7 alatt a drupal_add_js() működött, D8 nem engedi már. Nem ajánlott..(?) )

Drupal verzió: 
makgab képe

Működik az alert!

 $build['mymodule_table']['#attached']['library'][] = 'mymodule/mymodule.query.data';

Már csak azt kell megoldanom, hogy ne az egész oldal frissüljön, hanem csak a html table tartalma.

3
0
makgab képe

a MyModuleController.php-ban módosítottam:

...
public function query_data_refresh() {
...
$build['mymodule_table'] = [
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
      '#prefix' => '<div id="mymodule-query-div">', // add div around the html table
    ];
    // add lib, js
    $build['mymodule_table']['#attached']['library'][] = 'mymodule/mymodule.query.data.refresh';
 
    return $build;

A my.js tartalma:

setTimeout("location.href = '/mymodule/query/data/refresh'",5000);

Ez szépen működik is. D7 alatt volt egy elegáns megoldásom a .js-re:

(function($) {
Drupal.behaviors.myBehavior = {
  attach: function (context, settings) {
 
    //code starts
    $( document ).ready(function() {
      // Handler for .ready() called.
      setInterval(function(){refresh();}, 2000);
    });
 
 
    function refresh(){
 
    $.get('/mymodule/query/data/refresh', { },
    function(data){
        //request completed
        //now update the div with the new data
        $('#mymodule-query-div').html(data);
        }
    );
 
    }
    //code ends
 
  }
};
})(jQuery);

D7 alatt működött egyébként. Ez adott időközönként (2000ms) frissíti a "mymodule-query-div" div tartalmát, ami egy SQL eredményét adja vissza html table-ben. Majdnem ugyanaz a kódja a "/mymodule/query/data/refresh"-nek, mint a "/mymodule/query/data", de csak a tiszta html table tartalom kerül bele.

A FF konzolján ezt látom:
ReferenceError: jQuery is not defined
TypeError: drupalSettings.user is undefined

Mi lenne a szép megoldás D8 alatt? A D8 nem használja a jquery-t, ha jól látom és ezért nem fut le?

1
0
dj képe

$build['mymodule_table'] = [
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
      '#prefix' => '<div id="mymodule-query-div">', // add div around the html table
      '#suffix' => '</div>',
];
1
0

Üdv!
Dudás József

makgab képe

Köszönöm!
Ez valóban lemaradt, de ettől még nem működik.
A FF konzolban továbbra is ott van, hogy "jquery not defined"!

A jquery-vel van baja, nem jquery-t használ a D8. Gondolom...

upd.:
Lehet hogy megpróbálom átírni sima JS-re.
https://gist.github.com/joyrexus/7307312

0
0
makgab képe

Majdnem jó. A JS működik.
my.js:

setInterval(function(){ refresh(); }, 3000);
 
function refresh() {
 
  // Vanilla JS
  var httpRequest = new XMLHttpRequest()
  httpRequest.onreadystatechange = function (data) {
    // code
    document.getElementById("mymodule-query-data-div").innerHTML = httpRequest.responseText;
    // document.getElementById("mymodule-query-data-div").innerHTML = data;
    }
    httpRequest.open('GET', '/mymodule/query/data/refresh')
    httpRequest.send()
 
}

De a query_data_refresh() fv. (a ....Controller.php-ban) a teljes oldalt adja vissza, nem csak a HTML TABLE-t (tehát a div-be mégegyszer bekerül az egész oldal tartalma. :)).
Mit rontok el? Hogyan lehetne megadni, hogy csak a html table legyen a responseText-ben?

upd.:
próbáltam így:

public funtion query_data_refresh() {
...
// return $build; 
return $build['mymodule_table'];
}

De így meg üres lett a div.

0
0
makgab képe

Ha jól olvasom, akkor Response class-t kellene használni.

use Symphony\Component\HttpFoundation\Response;
...
public funtion query_data_refresh() {
...
return new Response($build);
}

De a logban:
Uncaught PHP Exception UnexpectedValueException: "The Response content must be a string or object implementing __toString(), "array" given."

Hogyan kellene használnom?

0
0
makgab képe

Működik! :)
A response használata:

...
use Symphony\Component\HttpFoundation\Response;
...
funtion query_data_refresh() {
...
   $build['mymodule_table'] = [
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
      '#prefix' => '<div id="mymodule-query-data-div">',  // add a <div>
      '#suffix' => '</div>',
    ];
 
    $response = new Response();
    $response->setContent( render($build) );
    return $response;
}
1
0
HF leon képe

Egész pontosan a 3-as verzióra. Könyvtárak js fájlok megadása esetén jelöld, hogy függ a jquery-től és akkor biztos betölti a jquery-t is, amikor a js-ed. Valamint, ha olyan jquery modul kell, amely nem része a drupal 8 alap rendszerének, akkor azt is be kell tölteni.

1
0