As I said, I'm not using DSL right now, I'm trying to create a simple hello world base on the Hello World example, it looks everything works fine except that I get runtime error the my injected "model is undefined", I think it because my module and my view need to be under a context this is my current code:
Main.hx
class Main {
static function main() {
var view = new HelloWorldView();
var module = new HelloWorldModule(view);
module.initialize();
}
}
HelloWorldController.hx
class HelloWorldController implements ICommandTrigger implements IHelloWorldController {
@inject
var model:IHelloWorldModel;
public function sayHello(who:String) {
// This line makes a runtime error "this.model is undefined"
model.setMessage("Hello $who");
}
}
How can I insert the view and the module into a context?
@context( name = 'applicationContext' ) {
why this line is necessary?
@context
is to provide scope for the "application" (where application is a very vague term) - this block basically represents the same thing as a root node in XML DSL and it creates ApplicationContext but it can be used just the same as a module (both module and application context implement the same interface IContextOwner
which exposes injector)... so to answer the second question - both module and context have injector, both have things mapped into the injector but they serve slightly different purpose... even though sometimes they can be used interchangeably (and there is a plan to allow that for more cases)override function _onInitialisation()
part) but that could be achieved by simply calling the controller directly from the Main class
The general rule is that popup blockers will engage if window.open or similar is invoked from javascript that is not invoked by direct user action. That is, you can call window.open in response to a button click > without getting hit by the popup blocker, but if you put the same code in a timer event it will be blocked. Depth of call chain is also a factor - some older browsers only look at the immediate caller, newer
browsers can backtrack a little to see if the caller's caller was a mouse click etc. Keep it as shallow as you can to avoid the popup blockers.
ILoginView
interface should contain trigger called something like onLoginRequested
which will be triggered when user clicks on the button (the setUsername
method is fine, no coupling to outside world).login
method (in my opinion it can even connect the trigger directly to the service call but that's just matter of taste)
//where you're creating the mappings
injector.mapClassNameToValue("Void->Void", model.someFunction);
//and in the view
@Inject
public var someFunction:Void->Void;
Object { _inputs: Array[0] }
) it worked before my changes :( please take a look.
I'm continue trying some things with hexMachina and I inject controller to my view:
@Inject
public var controller:IGeneratorController;
When I tried in module insert the view into injector like following, it didn't worked:
this.getInjector().mapToValue(ITransferView, transferView);
But this working:
this.getInjector().injectInto(transferView);
what injectInto do?
And also, I should to "attach" to view into the module (i.e "mapToValue") and not the module to view (i.e "injectInto"), I'm afraid that I not exactly understand the "Injector" thing...
IInjectorContainer
get an injector
object, but it's empty, so in the module I should "share" the module's injector with view's injector by this.getInjector().injectInto(transferView);
, but if I want add something to module injector I just need to "map it in" by this.getInjector().map methods
or by this._map etc...
// code:
injector.map(ClassX).toValue(x);
// english:
// every time when something requires ClassX provide it this specific value x ... aka singleton pattern
//-----
// code:
injector.map(ClassX).toType(ClassX);
// english:
// every time when something requires ClassX create a new instance of ClassX and provide that instance ... aka factory pattern
injector.injectInto(instance)
does following... it takes the instance you're passing in and goes through all the pre-reflected data (generated by the IInjectorContainer described above) and does injector.getInstance(_whatever type is the public variable type_)
which returns instances based on the mapping (or rules in other words) described above
this._map
is just a shortcut for this._injector.map
this._map(ILoginModel, LoginModel, '', true);
) so when I'm doing _get (i.e: this._get(ILoginModel)
) I'm getting a new instance of LoginModel
? (lol when I'm writing this it's makes more sense)
class Main extends App {
static function main() {
new Main();
}
override function init() {
super.init();
var injector = new Injector();
var vo = new VO();
vo.val = 'bar';
injector.map(VO).toValue(vo);
var container = new Container();
injector.injectInto(container);
}
}
class VO {
public var val = 'foo';
public function new() {
}
}
class Container implements hex.di.IInjectorContainer {
@inject
var _vo:VO;
public function new() {
}
@PostConstruct
public function enter() {
trace("vo.val:" + _vo.val);
}
}
Uncaught TypeError: Cannot read property 'val' of undefined