I have a spark Group container, but all its sub-components are MX components. I need to perform some operations on the MX components when the container is initialized. I tried to put the operations in the commitProperties function, but the sub-components are still null there. I tried moving them to the childrenCreated function, but they are still null. What function can I use for working with the components? Thanks.
protected override function commitProperties():void
{
var defaultFinishedDate:Date=new Date();
defaultFinishedDate.date--;
includeFinishedDateSelector.selectedDate=defaultFinishedDate;
}
The includeFinishDateSelector is null in this function, and thus I'm getting a run-time error. It's defined as:
<mx:DateField id="includeFinishedDateSelector" formatString="{GeneralUtils.DATE_FORMAT_STRING}"
enabled="{includeFinishedCheckBox.selected}" width="18%"/>
And as I said, its container is a spark Group container.
I would have expected the Flex life cycle method createChildren() is where you could do your operations. But you'd want to only do this work AFTER the super class has executed createChildren():
override protected function createChildren():void
{
super.createChildren();
// now do your thing
}
Another thing is that in the commitProperties() method you show above, you are not calling the super class method. That is a big no-no. The commitProperties() method is invoked by the Flex framework AFTER createChildren(). So theoretically, your approach with commitProperties() should have worked -- you might go back and put a call to super.commitProperties() in that code and give it another go.
Finally, if none of this works it may be due to the way Flex instantiates the children objects in MXML containers. So an approach that will definitely work is to listen for Flex life cycle events from the Group container. When the creationComplete event is dispatched by the Group, it is guaranteed that all of the children exist.
You can also try to wrap your code in callLater, it will essentially queue it to run on the next pass.
So in creationComplete try the following:
callLater(function():*{
var defaultFinishedDate:Date=new Date();
defaultFinishedDate.date--;
includeFinishedDateSelector.selectedDate=defaultFinishedDate;
});
It's not very elegant, but it should work.
Thanks to whomever tried to help. In the end I solved this by changing the direct container (parent) of the MX components to a spark container (it was originally an MX container in a spark container).
Related
I am experimenting making composable components using binding.scala. I would like to be able to have a component that can be used to wrap other components that are passed in. For example: a card component that wraps a styled box around any other arbitrary #dom function. I have attempted several approaches but have realized that because of the #dom macro, types seem to be more complicated than they appear.
Below, I have included an approach that doesn't work, but shows the intent. I want to be able to call wrapperMarkup and pass it contentMarkup.
I have found many examples where a data is passed into a #dom function and rendered, but no examples that show how to pass in another #dom function or the results from a #dom call.
Is there a good way to accomplish this?
type MarkupFun = ()=>Binding[Div]
#dom
def contentMarkup():Binding[Div] = {
<div>card Content</div>
}
#dom
def wrapperMarkup(f:MarkupFun):Binding[Div] = {
//<div>card wrapper {f.bind}</div> // What I want that doesn't work
<div>card wrapper {contentMarkup().bind}</div> // works but not what I want.
}
Soon after I posted the question, I found the obvious answer. I was failing to invoke the function before invoking bind.
#dom
def wrapperMarkup(f:MarkupFun):Binding[Div] = {
<div>card wrapper {f().bind}</div>
}
But, any other best practice suggestions would be great.
I dont really understand how they are useful. In the original article that introduced initializers this was the code sample:
App = new Backbone.Marionette.Application();
App.addInitializer(function(){
// add some app initialization code, here
});
App.addInitializer(function(){
// more initialization stuff
// for a different part of the app
});
// run all the initializers and start the app
App.start();
however, as far as I can understand, there is no difference between that^, and this:
App = new Backbone.Marionette.Application();
// add some app initialization code, here
// more initialization stuff
// for a different part of the app
The benefit of the latter code being that you can actually control the order of initialization code, whereas initializers are run in random order. So, what is the advantage of addInitializer?
I think the main wins are semantics - it's a very descriptive method name - and grouping of related functionality. I write my initializers with a named function, which helps with debugging and descriptiveness:
App.addInitializer(function startSomePartOfTheApp () {
});
Another useful feature is that the function is bound to the Application instance. This gives you the option of mixing in initializers, which is useful in larger apps.
But ultimately, you can achieve the same functionality in the way you've suggested.
Marionette apps have the initializer so that you can write code that runs after App.start()
Several uses of this :
Placing code in the .js file that will execute after the inline scripts are added
<script type='text/javascript'>
$(document).ready(function () {
App.start();
} );
</script>
Performing the initial fetch of a collection once you know the collection is defined
Setting up menu code
Fun Notes :
If the app is already started they run immediately
Keeps you clear of surprises with JavaScript function availability.
Good day!
I began writing my own basic JavaScript library for personal use and distribution a few days ago, but I am having trouble with one of the methods, specifically bind().
Within the method itself, this refers to the library, the object.
I went to Google and found function.call(), but it didn't work out the way I planned it--it just executed the function.
If you take a look at another method, each(), you'll see that it uses call() to pass values.
I also tried the following:
f.arguments[0]=this;
My console throws an error, saying it cannot read '0' of "undefined".
I would like to be able to pass this (referencing the library--NOT THE WINDOW) to use it in the event listener.
You can see it starting at line 195 of the JavaScript of this JSFiddle.
Here it is as well:
bind:function(e,f){
if(e.indexOf("on")==0){
e=e.replace("on","");
}
if(typeof f==='function'){
/*Right now, 'this' refers to the library
How can I pass the library to the upcoming eventListener?
*/
//f=f(this); doesn't work
//f.call(this); //doesn't work
//this.target refers to the HTMLElement Object itself, which we are adding the eventListener to
//the outcome I'm looking for is something like this:
/*$('h3').which(0).bind(function({
this.css("color:red");
});*/
//(which() defines which H3 element we're dealing with
//bind is to add an event listener
this.target.addEventListener(e,f,false)
}
return this;
},
Thank you so much for your help, contributors!
If, as per your comments, you don't want to use .bind(), rather than directly passing f to addEventListener() you could pass another function that in turn calls f with .call() or .apply():
if(typeof f==='function'){
var _this = this;
this.target.addEventListener(e,function(event){
f.call(_this, event);
},false)
}
Doing it this way also lets your library do any extra event admin, e.g., pre-processing on the event object to normalise properties that are different for different browsers.
So in this particular case you actually want to call JavaScript's built in bind method that all functions have.
f = f.bind(this);
f will be a new function with it's this argument set to whatever you passed into it.
Replace f=f(this); with f.apply(this);
Look at underscore code, here:
https://github.com/jashkenas/underscore/blob/master/underscore.js#L596
So, I was attempting to do something like the following:
if(Meteor.isServer){
Meteor.methods({connect_to_api: function(vars){
// get data from remote API
return data;
}});
}
if(Meteor.isClient){
Template.myTpl.content = function(){
Meteor.call('connect_to_api', vars, function(err,data){
Session.set('placeholder', data);
});
return Session.get('placeholder');
};
}
This seemed to be working fine, but, of course, now breaks in 0.5.9 as the Session object has been removed from the server. How in the world do you now create a reactive Template that uses a server-only (stuff we don't want loading on the client) method call and get data back from that Method call. You can't put any Session references in the callback function because it doesn't exist on the server, and I don't know of any other reactive data sources available for this scenario.
I'm pretty new to Meteor, so I'm really trying to pin down best-practices stuff that has the best chance of being future-proof. Apparently the above implementation was not it.
EDIT: To clarify, this is not a problem of when I'm returning from the Template function. This is a problem of Session existing on the server. The above code will generate the following error message on the server:
Exception while invoking method 'connect_to_api' ReferenceError: Session is not defined
at Meteor.methods.connect_to_api (path/to/file.js:#:#)
at _.extend.protocol_handlers.method.exception ... etc etc
Setting the session in the callback seems to work fine, see this project I created on github: https://github.com/jtblin/meteor_session_test. In this example, I return data in a server method, and set it in the session in the callback.
There are 2 issues with your code:
1) Missing closing brace placement in Meteor.methods. The code should be:
Meteor.methods({
connect_to_api: function(vars) {
// get data from remote API
return data;
}
});
2) As explained above, you return the value in the session, before the callback is completed, i.e. before the callback method had the time to set the session variable. I guess this is why you don't see any data in the session variable yet.
I feel like an idiot (not the first time, not the last). Thanks to jtblin for showing me that Session.set does indeed work in the callback, I went back and scoured my Meteor.method function. Turns out there was one spot buried in the code where I was using Session.get which was what was throwing the error. Once I passed that value in from the client rather than trying to get it in the method itself, all was right with the world.
Oh, and you can indeed order things as above without issue.
Even though I've been using mootools for a while now, I haven't really gotten into playing with the natives yet. Currently I'm trying to extend events by adding a custom addEvent method beside the original. I did that using the following code(copied from mootools core)
Native.implement([Element, Window, Document], {
addMyEvent:function(){/* code here */}
}
Now the problem is that I can't seem to figure out, how to properly overwrite the existing fireEvent method in a way that I can still call the orignal method after executing my own logic.
I could probably get the desired results with some ugly hacks but I'd prefer learning the elegant way :)
Update: Tried a couple of ugly hacks. None of them worked. Either I don't understand closures or I'm tweaking the wrong place. I tried saving Element.fireEvent to a temporary variable(with and without using closures), which I would then call from the overwritten fireEvent function(overwritten using Native.implement - the same as above). The result is an endless loop with fireEvent calling itself over and over again.
Update 2:
I followed the execution using firebug and it lead me to Native.genericize, which seems to act as a kind of proxy for the methods of native classes. So instead of referencing the actual fireEvent method, I referenced the proxy and that caused the infinite loop. Google didn't find any useful documentation about this and I'm a little wary about poking around under the hood when I don't completely understand how it works, so any help is much appreciated.
Update 3 - Original problem solved:
As I replied to Dimitar's comment below, I managed to solve the original problem by myself. I was trying to make a method for adding events that destroy themselves after a certain amount of executions. Although the original problem is solved, my question about extending natives remain.
Here's the finished code:
Native.implement([Element, Window, Document], {
addVolatileEvent:function(type,fn,counter,internal){
if(!counter)
counter=1;
var volatileFn=function(){
fn.run(arguments);
counter-=1;
if(counter<1)
{
this.removeEvent(type,volatileFn);
}
}
this.addEvent(type,volatileFn,internal);
}
});
is the name right? That's the best I could come up with my limited vocabulary.
document.id("clicker").addEvents({
"boobies": function() {
console.info("nipple police");
this.store("boobies", (this.retrieve("boobies")) ? this.retrieve("boobies") + 1 : 1);
if (this.retrieve("boobies") == 5)
this.removeEvents("boobies");
},
"click": function() {
// original function can callback boobies "even"
this.fireEvent("boobies");
// do usual stuff.
}
});
adding a simple event handler that counts the number of iterations it has gone through and then self-destroys.
think of events as simple callbacks under a particular key, some of which are bound to particular events that get fired up.
using element storage is always advisable if possible - it allows you to share data on the same element between different scopes w/o complex punctures or global variables.
Natives should not be modded like so, just do:
Element.implement({
newMethod: function() {
// this being the element
return this;
}
});
document.id("clicker").newMethod();
unless, of course, you need to define something that applies to window or document as well.