How to create Vaadin flow MprRouteAdapter for registered Vaadin 8 view with parameterized constructor? - migration

I have the following code snippet in Vaadin 8 to navigate to ShipmentView. The shipment view is registered with two parameter constructor:
navigator.addView("shipment", new ShipmentView("name", "shipmentId"));
navigator.navigateTo("shipment");
During the migration process, we decide to migrate ShipmentView later and use MprRouteAdapter first.
if the view does not require the two parameter constructor, we can have the following adapter and navigate with code UI.getCurrent().navigate(ShipmentViewRoute .class)).
#Route(value = "shipment", layout = MainLayout.class)
public class ShipmentViewRoute extends MprRouteAdapter<ShipmentView> {
public ShipmentViewRoute () {
this.setSizeFull();
}
}
With the two parameter "name"and "shipmentId", how can I create the Adapter?
Thanks you in advance.

I think the most straightforward way is just to hard-code those parameters in the constructor (or fetch them from wherever you would get them from when initializing the navigator in the old code).

Related

TYPO3 extbase: get some from FrontendUserGroupRepository

In a class file I can get all records from another repository that is not mine
$allUsergroups = $this->feGroupRepository->findAll();
How to make custom function to acomplish something like this on such a repository in the most correct way?
// magic default function that takes a uid list (or array) as argument
$someUsergroups = $this->feGroupRepository->findSomeByUidList('2,4,6,8');
Or can I extent an existing repository with my own custom functions, in this case based on $query->in(list)?
You can create your own method in your extensionRepository.php class
you can use :
in($propertyName, $operand)
or
contains($propertyName, $operand)
Contrarily, the methods in() and contains() accept multi-value data types as arguments (e.g. Array, ObjectStorage).
take a look how some other extension are doing stuff. (like the tx_news extension)
or read some docs here :
https://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html
Yes, you can extend another class in TYPO3 without any need to change any other code. It´s called Dependency Injection in ExtBase context.
First, create a new repository class your_ext/Classes/Domain/Repository/FrontendUserRepository.php and add below content to it:
<?php
namespace Tillebeck\YourExt\Domain\Repository;
class FrontendUserRepository extends \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository {
/**
* #param array $uidList
* #return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findByUidList(Array $uidList)
{
$query = $this->createQuery();
//$query->getQuerySettings()->setRespectStoragePage(false);
$query->matching(
$query->in('uid', $uidList)
);
return $query->execute();
}
/**
* #return string
*/
protected function getRepositoryClassName()
{
return get_parent_class($this);
}
}
Here we have implemented your method findByUidList with the required argument $uidList which needs to be an array.
Because repositories resolve their model names by their own class name, we need to change the method getRepositoryClassName to return the parent class name, in this case TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository.
But this alone won't work. We need to tell ExtBase that every time we inject or initialize a TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository, either by PHPDocBlock annotation #inject or by the objectManager->get, then we really want to initialize our new repository. This is done in TypoScript.
config.tx_extbase.objects {
TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository {
className = Tillebeck\YourExt\Domain\Repository\FrontendUserRepository
}
}
You can also restrict your change to your own extension alone by replacing config.tx_extbase with plugin.tx_yourext.
Last step: clear ALL cache, and possibly delete all files in typo3temp directory.
Now in your controller (or other class) you can run below code.
$uidList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', '2,4,6,8', true);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
$this->frontendUserRepository->findByUidList($uidList)
);
I have tested above solution in TYPO3 7.6 and it works. Dependency Injection has existed since version 6.1.
This is by my definition the must correct way, as you asked, to implement this feature in your own TYPO3 extension.

How to use variables to refer to Components in codename one?

I created a UI with the UIBuilder.
Instead of always using the findXXXX (), I would love to do something like this in the Statemachine:
public class Statemachine ... {
private Container c;
private Tabs t;
initVars () {
initAll();
}
....
private initAll () {
Container c = findContainer();
Tabs t = findTabs();
...
}
}
and use them as c.getYYY().
Is this possible? If yes, how?
Yes you can do that, but not advisable.
The danger of it is when you have 2 components with the same name on different forms, this may reference wrong component and may be hard to debug.
If you sure can deal with the above, you can declare and initiate the variables inside Statemachine class but outside of all methods as a private global variable.
public class Statemachine ... {
private Container c = findContainer();
private Tabs t = findTabs();
initVars () {
}
....
}
You can't do that in the current GUI builder since the current GUI builder creates forms dynamically and discards them during navigation.
The new GUI builder uses a completely different architecture and will work exactly like that: 1 class per one UI form. So you will have variables for every field.
You can see this in action here.
Note that at this time the GUI builder is still in pre-beta stage although we are heavily committed to it and its architecture.

Specify view provider type when creating new WinRT view

Trying to understand the potential use of multiple views in a WinRT app. I can create a new view, which runs on its own dispatcher thread and can be switched in/out, with CoreApplication.CreateNewView. I can't figure out how to specify how to pass a view provider in the first argument. If I have a bare app in C# (though the same holds if I use Application.Start):
public class Program
{
static void Main()
{
CoreApplication.Run(new MyViewSource());
}
}
public class MyViewSource : IFrameworkViewSource
{
public IFrameworkView CreateView()
{
return new MyView();
}
}
public class MyView : IFrameworkView
{
// ...
}
If I want to create a new view with the current view provider (I suppose the one that created the currently active view), I can do
CoreApplication.CreateNewView("", "foo");
The API documentation says the 1st parameter is "The class ID of the view provider for the new view." What does that refer to? Anything I tried gave the following:
Additional information: Class not registered (Exception from HRESULT: 0x80040154 > >(REGDB_E_CLASSNOTREG))
First parametr is name of your new view class.
The class ID of the view provider for the new view. If this parameter is null, use the current view provider.
If you left first parameter null then your new view will have a current view class reperesentation.
So if You want to create a new View with a cutsom class, you have to create this class and put into first parameter.
Like this:
public class MySecondView : IFrameworkView
{
// ...
}
And then:
CoreApplication.CreateNewView("MySecondView", "foo");
Let me know about success of this operation becouse I'm not sure about my code.
Check the link below for perfect example.
Refernce:
MSDN Microsoft Multi Windows For An App
Sample Code Example
Using Multiple Views in Windows Store Apps

Yii: attaching events to models

I have a User model which is bundled in a module installed on my Yii application. This module is third party and I do not want to alter its code.
I also have a Cv Model that has a BELONGS_TO relation with the User model.
My question is: How can I delete the cv when a user is deleted ?
I know that I can achieve this with on delete cascade ... on mysql. However, i do need to delete other data such as a photo, files, etc.
What I have tried
I have created a component that is preloaded on my application. This component attaches to an onAfterDelete event
class EventListener extends CComponent
{
public function init() {
Yii::import("application.modules.users.models.User");
User::model()->attachEventHandler('onAfterDelete', array($this, 'deleteUser'));
}
public function deleteUser($event)
{
// stuff here ...
}
}
However this does not work.
Any suggestions ?
This may help you.
User::model() is a singleton
$user1 = User::model();
$user2 = new User; // will be used in insert action
$user3 = User::model()->findByPk(10); // will be used in update/delete action
$user1, $user2 and $user3 are completely different objects.
You can attach events to objects, in this case you have to add events to all these 3 objects individually.
$user1->attachEventHandler(...);
$user2->attachEventHandler(...);
$user3->attachEventHandler(...);
look like Yii does not provide any way to add events at Class level.
Well, guys, I have just stumbled upon the same problem and I solved it this way:
You should use the init() of a Model, not your event listener collection class.
In my case I have devModel class:
public function init()
{
parent::init();
$this->onLicenseUpdated = array(new MEventProcessor, 'licenseUpdateHandler');
}
And the handler is licenseUpdateHandler($event) in a MEventProcessor class.
This way every time you work with model instance, it'll call init() for every object and attach the event handler to every instance of this Model.
Now any time the event (in my case onLicenseUpdated()) is invoked for the model - the handler will be called too.
You could also to use Behaviors.
1 - behaviors can listen to events : you just have to override their events() method
class MyBehavior extends Behavior {
public function events() {
return [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
];
}
public function beforeValidate($event) {
// ...
}
}
2 - although it is more common to attach a behavior to a component in the component's behaviors() method, you can also attach them dynamically and keep the original code unmodified :
use app\components\MyBehavior;
// attach a behavior object
$component->attachBehavior('myBehavior1', new MyBehavior);
You will find some useful documentation here :
yii 1 : http://www.yiiframework.com/doc/api/1.1/CBehavior
yii 2 : http://www.yiiframework.com/doc-2.0/guide-concept-behaviors.html

Mef, passing parameters to a module

I'm studying MEF and I'm not able to resolve a problem.
I have a main application, called MainMEF, and a simple module, called SimpleModule. This one consists of a single UserControl which is loaded dynamically.
When MainMEF starts up, I would be able to pass to the module a reference to main application contained into MainMEF.
How could I fix this?
Lots of questions regarding this already.
You could pass it after initialisation using a property:
How do I populate a MEF plugin with data that is not hard coded into the assembly?
Or use MEF constructor parameters:
MEF Constructor Parameters with Multiple Constructors
The export looks something like this:
[Export(typeof(ITest))]
class Test : ITest
{
void Test()
{ }
[ImportingConstructor] //<- This is the key bit here
void Test(object parameter)
{ }
}
Then when composing your catalog do this:
catalog.ComposeExportedValue( /* parameter here */);
catalog.ComposeParts(this);