I'm testing ATK4 for some scenarios to decide, if I can go with it. One of these Scenarios is a status page for groups and members, which should reload automatically the grids, which contains dynamic group and member informations.
The grid reload I've implemented like described in this Thread Agile toolkit : how to automatically reload grid
Here's the code for the members page:
<?php
class page_members extends Page {
function init(){
parent::init();
$page = $this;
$page->api->stickyGET('group_id');
$grid = $page->add('Grid');
$model = $grid->setModel('Member');
if ($_GET['group_id'])
$model->addCondition('group_id', $_GET['group_id']);
$page->js(true)->univ()->setInterval(
$grid->js()->reload()->_enclose()
,10000);
}
}
If I call it from the Browser with the group_id parameter, it works like expected. But this page will called from a group page into a frameURL with the following code:
<?php
class page_groups extends Page {
function init(){
parent::init();
$page = $this;
$grid = $page->add('Grid');
$model = $grid->setModel('Group');
$grid->addColumn('button','members');
if($_GET['members']){
$grid->js()->univ()
->frameURL('Members' ,$page->api->url('../members',array('group_id'=>$_GET['members'])))
->execute();
}
$page->js(true)->univ()->setInterval(
$grid->js()->reload()->_enclose()
,10000);
}
}
If I click on button 'members' from group 1, the members page for group 1 open in a frame and refreshes every 10 seconds. That's okay. But if I close the frame and open a new frame by clicking on 'members' button from group 2, the grid cycling through group 1 and 2 while refreshing the grid.
I think, the problem is the timer, created by the setInterval()
function, which has to be cleared by clearInterval(id)
before the frame is closed. The setInterval()
function has a return value, but I don't know, how I can handle it over to the clearInterval(id)
function in the ATK4 Framework?
Problem exists because setInterval
is added to global window
object and because window
object itself is not reloaded (using AJAX we only reload parts of DOM tree) setInterval
method continues to be called even when you close modal dialog or reload "page" container.
In short it is written here: http://www.w3schools.com/jsref/met_win_setinterval.asp
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
So, possible workarounds in this case will be one of these:
setTimeout
instead of setInterval
and reload widget with new setTimeout
call every timeclearInterval
when you close modal dialog window to get rid of old globally registered intervalsA lot of useful information about setInterval can be found here: https://developer.mozilla.org/en/docs/Web/API/window.setInterval
class page_company extends Page
{
function init()
{
parent::init();
$page = $this;
$grid = $page->add('Grid');
$model = $grid->setModel('Company');
$grid->addColumn('button','company');
if ($_GET['company']) {
$grid->js()->univ()
->frameURL('Employees', $page->api->url('../employee', array(
'company_id'=>$_GET['company'])))
->execute();
}
}
}
class page_employee extends Page
{
function init()
{
parent::init();
$page = $this;
$page->api->stickyGET('company_id');
$grid = $page->add('Grid');
$model = $grid->setModel('Employee');
if ($id = $_GET['company_id']) {
$model->addCondition('company_id', $id);
}
// NOTE:Important is that you add setTimeout JS chain to grid not page!
// That's because you reload only grid and you need to receive
// this JS chain from server on each reload to keep it reloading.
// $page is not reloading, only $grid is!
$grid->js(true)->univ()->setTimeout(
$grid->js()->reload()->_enclose()
,5000);
}
}
This way everything works fine except situation when you close one modal dialog and open new one in less that 5 seconds (setTimeout time). Problem is the same - setTimeout
also is added to global window
object and as result it still get executed after these 5 seconds even if you close your modal dialog in the mean time.
With newest ATK commit in Github you can now initialize periodic reloads of any View with just 1 simple chain.
So instead of something like this (which don't work):
$grid->js(true)->univ()->setTimeout(
$grid->js()->reload()->_enclose()
,5000);
now you can simply call:
// reload grid every 5 seconds
$grid->js(true)->reload(null,null,null,5000);
NOTE: you should apply this to exactly that View object which you want to reload periodically.