How to get all child targets - stimulusjs

My question is how to get all nested controllers data-target values?
Example:
Event has multiple tasks. So, I have Event and Task controller.
I want to get content values from tasks to Event controller.
Tried something like this:
const nodes = this.data.element.childNodes
Or this.contentTarget.dataset
In Task view I have:
data-target="task.content event.content"
So, there is one instance of Event controller, and n of Task controllers. How to get all task titles?

If you have all the nodes tagged with data-target="event.content", you don't need to deal with the Task controllers at all, you can just reference them in the EventController as
class EventController {
static targets = ["content", ...];
doSomething() {
const targets = this.contentTargets;
...
}
}

Related

Notifying main thread object when background operation finishes in kotlin native

I'm building an iOS app using kotlin native and having problems with inter-thread communication.
In my app there is a class that makes an http request in a background thread (using coroutines) and needs to update the parent class state when the operation finishes. Something like this:
class Feed {
var items
fn update() {
asyncHttpRequest("http://myservice.com") { newItems ->
CoroutineScope(Dispatchers.Main).launch {
items = newItems
}
}
}
}
This fails because the feed object is frozen when passed as part of the lambda function context so it cannot be updated with the new items when the http background operation finishes.
What is the best way to design and implement something like this in kotlin-native?
Thank you!
One option would be to use atomics for modifying state concurrently:
AtomicReference
touchlab/Stately

Update Checked State of Handler in E4

In E3 we had a couple of handlers that were to be checked, and so the handler had to figure out when to be checked. Back then that was an easy task:
public class MyHandler extends AbstractHandler implements IElementUpdater {
#Override
public void updateElement(UIElement element, Map parameters) {
element.setChecked(calculateCheckState());
}
}
I found this similar question, but it's much broader (updating all commands, while I only want to set the checked state whenever the framework seems it necessary). Since tool and menu items can be check or radio items, this has to be possible somehow.
So how do I set the check state of a handler in E4?
You can set the check (selected) state in the #CanExecute method of the handler using something like:
#CanExecute
public boolean canExecute(MItem item)
{
item.setSelected(... checked state ....);
return true;
}
For a menu item the #CanExecute method is called every time the menu is displayed.
For a tool bar item you may need to use the IEventBroker UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC event to force the method to run.
eventBroker.send(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, argument);
argument can be
UIEvents.ALL_ELEMENT_ID to update all items.
The id of a single item to be updated.
A Selector (org.eclipse.e4.ui.workbench.Selector) to select the items to be updated.

Building a event-based application-wide cron component

What I'm trying to achieve is creating an application that is highly modular. I'm trying to create a cron script which addresses all the cron scripts that need to be fired in all the sub-modules. What I would actually would like to do, is create an event, say runCron that gets fired from a CController and then hook into that when it get's raised from within the sub modules with onRunCron methods. Outlining what I'm trying to do:
Application
|- CronController.php - Raise the event 'RunCron', not knowing which modules will fire after this.
|- Modules
|- Nodes
|- Observe the event 'onRunCron' and run own cron script
|- Users
|- Observe the event 'onRunCron' and run own cron script
What I think I will need to do according to Yii's event system, is create the event and raise it at an application-level (that is still what I'm trying to do) but then; I also need to assign the callbacks from the submodules on an application-level in the controller. Which I do not want, since when a submodule gets added / deleted, the application needs to be adjusted, which does not sound modular at all.
Could someone line out the basics of setting up a event like this and making it as modular as possible? Since I think I'm looking at this completely the wrong way.
Edit (solution):
Thanks to acorncom's answer I've managed to work out the following system.
application.components.CronSingleton
<?php
class CronSingleton extends CApplicationComponent {
/**
* Make sure we "touch" the modules, so they are initialised and are able to attach their listeners.
*/
public function touchModules () {
$modules = Yii::app()->getModules();
if (!empty($modules)) {
foreach ($modules as $name => $module) {
Yii::app()->getModule($name);
}
}
}
/**
* This method should be run to run the cron. It will commense all the procedures in cronjobs
*/
public function execCron($caller) {
$this->touchModules();
$this->onStartCron(new CEvent($caller));
$this->onRunCron(new CEvent($caller));
$this->onExitCron(new CEvent($caller));
}
/**
* Raise an event when starting cron, all modules should add their listeners to this event if they would like to fire something before running the cron.
*/
public function onStartCron ($event) {
$this->raiseEvent('onStartCron', $event);
}
/**
* Raise an event when running cron, all modules should add their listeners to this event to execute during cron run. Mosty this event should be used.
*/
public function onRunCron ($event) {
$this->raiseEvent('onRunCron', $event);
}
/**
* Raise an event when cron exits, all modules should add their listeners to this event when cron exits.
*/
public function onExitCron ($event) {
$this->raiseEvent('onExitCron', $event);
}
}
?>
application.controllers.CronController
<?php
class CronController extends Controller
{
public $layout='//layouts/bare';
public function actionIndex($k) {
Yii::app()->cron->onStartCron = array($this, 'startcron');
Yii::app()->cron->onRunCron = array($this, 'runcron');
Yii::app()->cron->onExitCron = array($this, 'exitcron');
Yii::app()->cron->execCron($this);
}
public function startcron(){
var_dump('CronController - Starting cron');
}
public function runcron(){
var_dump('CronController - Run cron');
}
public function exitcron(){
var_dump('CronController - Ending cron');
}
}
?>
application.modules.admin.AdminModule
<?php
class AdminModule extends CWebModule
{
public function init()
{
// this method is called when the module is being created
// you may place code here to customize the module or the application
// import the module-level models and components
$this->setImport(array(
'admin.models.*',
'admin.components.*',
));
Yii::app()->cron->onRunCron = array($this, 'runCron');
}
public function runCron($event) {
var_dump('AdminModule - Run cron');
}
public function beforeControllerAction($controller, $action)
{
if(parent::beforeControllerAction($controller, $action))
{
// this method is called before any module controller action is performed
// you may place customized code here
return true;
}
else
return false;
}
}
?>
This "proof of concept" setup manages to print out the following result, exactly what I wanted it to do:
string(30) "CronController - Starting cron"
string(25) "CronController - Run cron"
string(22) "AdminModule - Run cron"
string(28) "CronController - Ending cron"
I think you'll want to do something like the following (note: this hasn't been tested, but it should work conceptually).
Create a CApplicationComponent for your cron system. Having it be an application component (registered in your config/main.php file) makes it accessible from anywhere in your app / modules / sub modules / controllers, etc
Have your cron component handle the registration of events / firing of events. Refer to the Yii events page for more info on the details of how this works. Note: you can create your own custom events that subclass the main CEvent class if you need to pass in additional parameters about your events.
Have your modules register as event handlers with your cron component as they initialize.
Have your controller fire off an event to your cron component.
One potential gotcha. I'm not sure whether modules or components are registered first (I believe components should be, but it's worth testing). If your cron component is loading after the modules that are trying to register events with your cron component, then you may want to preload your cron component. There are a few other hacks you can try if that doesn't work (come back and ask for more details).
Oh, and let us know how it goes!
Have you checked the wikis on yii's website about events? I think it's a good place to start, then if you still have some questions we could help you!
Events explained
Behaviors & events

MVVM and NavigationService

One of the many benefits of implementing any pattern is to have a separation of concerns between the different layers in an application. In the case of Silverlight and MVVM it is my opinion that the NavigationService belongs to the UI.
If the NavigationService belongs to the UI then it should be used in the XAML code behind, but the commands happens on the ViewModel. Should I raise an event on the Command in the ViewModel and let the View handle the event and call the Navigation? That sounds a little absurd if all I'm doing is simply navigating to another page. Shouldn't I just handle the UI event directly and navigate from there?
View Control Event -> ViewModel Command -> Raise Event -> View
Handled Event -> Navigation
or
View Control Event -> View Handled Event -> Navigation
There are two documented approaches to this problem
Implementing the navigation using MVVM Light's messaging functionality This approach was put forward by Jesse Liberty in Part 3 his MVVM Ligtht soup to nuts series. His approach is to send a message from the command to the view indicating that a navigation operation should take place.
Implementing a ViewService that handles the navigationThis approach was Laurent Bugnion's response to Jesse's post. This implements a service that handles all navigation operations triggered by the view models.
Both approaches deal only with navigation in WP7 applications. However, they can be adapted to Silverligt applications too.
Jesse's approach is easier to use in SL as it does not require access to the root visual. However, the navigation code gets distributed in several places and requires code behind to do the actual navigation.
Laurent's approach requires access to the root visual - which is used for accessing the built-in navigation functionality. Getting access to this, as shown in Laurent's code, is no big deal in WP7 applications. In SL applications, however, it is slightly more complicated as there is no sourrounding frame. However, I alreay implented the pattern for SL in one of my projects using an attached property do do the required wiring - so although requires more work, it is usable for SL as well.
So concluding - although, Jesse's approach is easier to implement, personally I prefer Laurent's approach for it is cleaner architecture - there is no code behind required, and the functioality is encapsulated into a separate component and thus located at a single point.
A bit late to this question, but it is relevant and will hopefully be of benefit to someone. I had to create a SL4 application with MvvmLight and wanted to use a navigation service wrapper that was mock-able and could be injected into the ViewModel. I found a good starting point here: Laurent Bugnion's SL4 sample code samples from Mix11 which includes a navigation service demo: Deep Dive MVVM Mix11
Here are the essential parts for implementing a mock-able navigation service that can be used with Silverlight 4. The key issue is getting a reference to the main navigation frame to be used in the custom NavigationService class.
1) In MainPage.xaml, the navigation frame is given a unique name, for this example it will be ContentFrame:
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
Source="/Home" Navigated="ContentFrame_Navigated"
NavigationFailed="ContentFrame_NavigationFailed">
<!-- UriMappers here -->
</navigation:Frame>
2) In MainPage.xaml.cs, the navigation frame is exposed as a property:
public Frame NavigationFrame
{
get { return ContentFrame; }
}
3) The navigation service class implements the INavigationService interface and relies on the NavigationFrame property of MainPage.xaml.cs to get a reference to the navigation frame:
public interface INavigationService
{
event NavigatingCancelEventHandler Navigating;
void NavigateTo(Uri uri);
void GoBack();
}
public class NavigationService : INavigationService
{
private Frame _mainFrame;
public event NavigatingCancelEventHandler Navigating;
public void NavigateTo(Uri pageUri)
{
if (EnsureMainFrame())
_mainFrame.Navigate(pageUri);
}
public void GoBack()
{
if (EnsureMainFrame() && _mainFrame.CanGoBack)
_mainFrame.GoBack();
}
private bool EnsureMainFrame()
{
if (_mainFrame != null)
return true;
var mainPage = (Application.Current.RootVisual as MainPage);
if (mainPage != null)
{
// **** Here is the reference to the navigation frame exposed earlier in steps 1,2
_mainFrame = mainPage.NavigationFrame;
if (_mainFrame != null)
{
// Could be null if the app runs inside a design tool
_mainFrame.Navigating += (s, e) =>
{
if (Navigating != null)
{
Navigating(s, e);
}
};
return true;
}
}
return false;
}
}

Simple example of DispatcherHelper

I'm trying to figure out how can I use DispatcherHelperftom MVVM light toolkit in SL, but I can't find any example.
From home page of this framework I know that
DispatcherHelper class, a lightweight class helping you to create
multithreaded applications.
But I don't know how to use it.
How and for what I can use it?
You only need the DispatcherHelper when yo want to make changes to components on your UI thread, from code that runs on a different thread. E.g. in an Silverlight application you call a web service to retrieve some data asynchroneously, and now want to inform the Ui that the data is present via a OnNotifyPropertyChanged event.
First you have to initialize the DispatcherHelper. In Silverlight you do this in Application_Startup:
//initialize Dispatch helper
private void Application_Startup( object sender, StartupEventArgs e) {
RootVisual = new MainPage();
DispatcherHelper.Initialize();
}
In WPF the initialization is done in the static constructor of you App class:
static App() {
DispatcherHelper.Initialize();
}
Then in your event, handling the completion of your asnc call, use the following code to call RaisePropertyChanged on the UI thread:
DispatcherHelper.CheckBeginInvokeOnUI(
() => RaisePropertyChanged(PowerStatePropertyName)
);
DispatcherHelper.BeginInvokeOnUl expects an Action so you can use any code in here just use
DispatcherHelper.CheckBeginInvokeOnUI(
() => { /* complex code goes in here */ }
);
to do more complex tasks.