Stopping reload timer for grid in ATK4 - atk4

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?

Description:
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:
use setTimeout instead of setInterval and reload widget with new setTimeout call every time
use clearInterval when you close modal dialog window to get rid of old globally registered intervals
A lot of useful information about setInterval can be found here: https://developer.mozilla.org/en/docs/Web/API/window.setInterval
Testcase:
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.
Last Edit
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.

Related

Codename One RESTfulWebServiceClient Threads

I have a simple programme that calls a rest service and displays the output.
The problem is the display is being updated before the rest method returns.
I've tried to use the invoke and block, however the .find method appears to run in it's own thread? asynchronously
the Sys output goes like this;
Before
After
surname
System.out.println("Before");
userClient = new RESTfulWebServiceClient("http://localhost:8080/MyService/api/person");
Display.getInstance ()
.invokeAndBlock(() -> {
userClient.find(
new Query().id("id"), rowset -> {
for (Map m : rowset) {
person = new JSONObject(m);
System.out.println(person.getString("surname"));
}
}
}
System.out.println("After");
I have found a workaround that works.
As I can see the problem is the .find method of the RESTfulWebServiceClient class. The line NetworkManager.getInstance().addToQueue(req); creates an asynchronies call to the rest network service and returns the method before the call is made.
To get around this I recreated the RESTfulWebServiceClient class in my project and copied the source from github.
I then changed the
NetworkManager.getInstance().addToQueue(req);
to
NetworkManager.getInstance().addToQueueAndWait(req);
This causes the the method to complete the rest call before returning.

Behat, PhantomJS - wait for page load after clicking link?

I'm using Behat 3 and PhantomJS 2. Currently I have a scenario defined as such:
#javascript
Scenario: I visit the blog through the Blog & Events menu.
Given I am an anonymous user
And I am on the homepage
And I follow "Link Text"
Then I should be on "/path-to-page"
When I run this with Goutte it's fine. When I run this with vanilla Selenium, it's fine (it launches a browser I can see). However, when I configure Selenium to point the webdriver host to PhantomJS, it explodes on Then I should be on "/path-to-page" claiming it's still on /.
If I add the following wait step:
#javascript
Scenario: I visit the blog through the Blog & Events menu.
Given I am an anonymous user
And I am on the homepage
And I follow "Link Text"
And I wait 4 seconds
Then I should be on "/path-to-page"
Then my scenario passes in the green, all good.
Is there a way to get PhantomJS to wait for the page to load before checking the current path? I don't want to depend on arbitrary timeouts. I need a headless solution and PhantomJS seems to be pretty well supported, but if I can't do something as simple as clicking a link and verifying the page that was loaded without adding random waiting steps everywhere, I might need to re-evaluate my decision.
Try using this implicit wait in your feature context. In my experience it has helped.
/**
* #BeforeStep
*/
public function implicitlyWait($event)
{
// Set up implicit timeouts
$driver = $this->getSession()->getDriver()->getWebDriverSession();
$driver->timeouts()->implicit_wait(array("ms" => 10000));
}
I was having the same issue, and doing something like this fails because its using the state of the current url:
$this->getSession()->wait(10000, "document.readyState === 'complete'");
So my workaround for this was adding a variable to the page every time a step is done. When I link is clicked, the variable will no long exist, this will guarantee that am working with a different page.
/**
* #AfterStep
*/
public function setStepStatus()
{
$this->getSession()->evaluateScript('window.behatStepHasCompleted = true;');
}
/**
* #When /^(?:|I )wait for the page to be loaded$/
*/
public function waitForThePageToBeLoaded()
{
$this->getSession()->wait(10000, "!window.behatStepHasCompleted && document.readyState === 'complete'");
}
You can always make use of a closure function to encapsule your steps, just as mentioned in the docs. Through it, you can get your steps to run when they're ready. Let's implement a spinner function:
public function spinner($closure, $secs) {
for ($i = 0; $i <= $secs; $i++) {
try {
$closure();
return;
}
catch (Exception $e) {
if ($i == $secs) {
throw $e;
}
}
sleep(1);
}
}
What we're doing here is wait for a number of seconds for the closure function to run successfully. When the time's run out, throw an exception, for we want to know when something's not behaving correctly.
Now let's wrap your function to assert you're in the right page within the spinner:
public function iShouldBeOnPage($wantedUrl) {
$this->spinner(function() use($wantedUrl) {
$currentUrl = $this->getSession()->getCurrentUrl();
if ($currentUrl == $wantedUrl) {
return;
}
else {
throw new Exception("url is $currentUrl, not $wantedUrl");
}
}, 30);
What we're doing here is wait up to 30 seconds to be on the url we want to be after clicking the button. It will not wait for 30 secs, but for as many secs we need until current url is the url we need to be at. Applying it in your function within the *Context.php will result in it being applied in every step you call it within your Gherkin files.

MVVM Light message being received rarely, otherwise never received

I am having a strange issue with MVVM Light messaging. I am using it through my application and it has worked fine. I am now having a problem where my message is received roughly 10% of the time I try to send it. I'm assuming it gets shot off in to oblivion the other 90% of the time and I receive no errors and my application goes on as if nothing happened.
What I have is a context menu in a view that has a collection of statuses. Each user has a status and you can change it via this context menu. Every time the status changes I need to broadcast a message to another view model. This is the message that fails. Here is some code, feel free to ask me more questions if this is not clear enough for you.
This is located in my constructor, fired from a context menu item click:
this.UpdateUserStatus = new RelayCommand<UserStatusVM>(x =>
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
UpdateStatus(x);
}));
UpdateStatus method from relay command:
private void UpdateStatus(UserStatusVM status)
{
var userStatusEventId = _userService.CreateUserEvent(status.Id, CurrentUser.Id);
//This returns a business object that I would like to send
//over the wire to the other view model
var userEvent = _userService.GetUserEvent(userStatusEventId);
if (userEvent != null)
{
Messenger.Default.Send<UserEvent>(userEvent, "Broadcast");
}
//These fire off a collection changed event
CurrentUser.StatusId = status.Id;
CurrentUser.Status = status.Name;
CurrentUser.UpdatedDate = DateTime.Now;
CurrentUser.IsOnDuty = UserStatuses.IsOnDuty(status.Id);
}
and the message reception in the other view model:
Messenger.Default.Register<UserEvent>(this, "Broadcast", (userEvent) =>
{
proxy.Invoke("NewUserEvent", userEvent);
});

ADF Jdeveloper Refresh Parent Form on Popup close

I want to refresh(update few fields) on my parent form when OK button is clicked on Poup Dialog. But it does not refresh the fields. I have also set partialTriggers for the fields with Popup Id.
My Jdeveloper version is 11.1.1.7
Thanks
Umer Farooq
All you need is linking the OK button action (or action listener) property with a call through an EL to a method provided on a managed bean. Then, in it you should refresh either each component or just the form/parent component keeping all of them(by registering it's bind into a partial target of the ADF context). The method should be similar to this example:
public String refresh() {
AdfFacesContext.getCurrentInstance().addPartialTarget(formToRefresh);
return null;
}
private RichPanelFormLayout installDisable; //this should be the binding to the JSF form
public void setInstallDisable(RichPanelFormLayout installDisable) {
this.installDisable = installDisable;
}
public RichPanelFormLayout getInstallDisable() {
return installDisable;
}
I would need to see what you implemented in your code in order to provide you the "best" solution overall - as theres multiple ways to implement a dialog in a popup. However, here's a couple options depending on how your Popup Dialog is programmed:
Dialog Listener - use this if you use the built-in buttons of a dialog box. You'll need a managed bean for your jspx/jsf page. Create a Dialog Listener on your managed bean that is on your Dialog box. See below for a example of a dialog listener.
public void myDialogListener(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.yes)) {
// do something...
} else if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.no) {
//do something...
}
}
Return Listener - if you're running a task flow as a popup dialog, on your button, then add a ReturnListener to your page's managed bean. This fires whenever a your popup/dialog is closing.
public void myReturnListener(ReturnEvent returnEvent) {
//do something...
}
Otherwise, i'd add a an ActionListener to your manual button as Endrik suggests.
Now for refreshing your components, use this method in your managed bean, i use it all the time in my projects:
public void refreshComponent(UIComponent comp) {
RequestContext rContext = RequestContext.getCurrentInstance();
rContext.addPartialTarget(comp);
}
To use it, you need to bind your Form's UI components to a managed bean. Then feed in the UI Component's bean property into the method.
For example, below will refresh a Rich Output Text that i have bound to a managed bean:
private RichOutputText myOutputText;
public void refreshMyStuff() {
refreshComponent(myOutputText);
}
Have a good one.

How to Profile (Debug) ExtJS EventPipe / Events

I am working on a relatively large ExtJS MVC application with around >40 Controllers, >100 Stores, >100 Models and so on. I don't follow the possible MVC way strict so I implemented a lazy controller initialization which initialize the controller first when it is required and so the stores. I also don't register any view within any controller, but that simply cause I don't need to.
Now it comes that forms (opened within a Ext.window.Window) take around 1-2 second until they shown up while the same form within a rather small project pops up immediately.
So the form (layout) can not be the problem here what brought me to the events. But I don't really know how would be the best way or is there already a good tutorial how to do this. I guess it would be nice to profile this, to see how long the whole pipe takes (not only the EventPipe itself).
Event structure:
Most of the events get registered via control() of the responsible controller. All other events are at most registered with { single: true }. The windows get closed and reinstantiated when reused.
I'm afraid but ExtJS doesn't provide any event profiling. It use custom event system.
Here is how I see the solution of this issue.
There are Ext.util.Event class that provides functionality to dispatching and handling any event used in the framework and Ext.app.EventBus that provide single point to dispatch all framework events (fireEvent is just wrapper for Ext.app.EventBus.dispatch method).
Classes are private so I recommend to see its source code.
You can override these classes to see how much it takes from calling Ext.app.EventBus.dispatch method and calling event listener within Ext.util.Event.fire method smth like that (EventProfiler is supposed to be your own class)
Ext.app.EventBus
dispatch: function (/* event name or Ext.util.Event */event, /* Target class */ target, args) {
//start timing
var start = new Date();
/* ... */
for (i = 0, ln = events.length; i < ln; i++) {
event = events[i];
// Fire the event!
if (event.fire.apply(event, Array.prototype.slice.call(args, 1)) === false) {
return false;
}
// start event profiling
// here we are sure that event is dispatched and it's instance of Ext.util.Event
EventProfiler.startProfile(event, /* time passed from dispath method started */new Date() - start);
}
/* rest of dispatch method call */
}
Ext.util.Event
fire: function () {
/* ... */
if (listener.o) {
args.push(listener.o);
}
EventProfiler.endProfile(this);
if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
return (me.firing = false);
}
/* ... */
}

Resources