I'm trying to figure out when a store is ready to be used within my app.
I figured from the doc that if I want to display information from my store, I should listen to the 'refresh' event of my store to get notified when it has been changed (and thus also when it is first loaded).
However, using the following example:
Ext.define('MyApp.store.Config', {
extend: 'Ext.data.Store',
config: {
autoLoad: true,
autoSync: true,
model: 'MyApp.model.Config',
listeners: {
refresh: function() {
console.log(Ext.StoreManager.get('Config').getAt(0))
}
}
} });
the 'console.log' gets called twice at startup, and it fails the first time (it seems that the Store is not loaded yet). My model uses a proxy (type ajax, and a json reader).
Could someone tell me how I should proceed to avoid this error?
Thanks!
I found the reason...
I was declaring the 'stores:['Config']' property both in my app.js and in on of my controllers.
Quite hard to spot but my mistake...
Related
I am using Spartacus 4.2 and i am tracking a bunch of events via GTM.
I have configured gtm to track some custom and standard events but when i try to add the OrderPlacedEvent i get the following error:
Type 'TmsConfig' has no properties in common with type 'Config'
The import for OrderPlacedEvent looks like this:
import { OrderPlacedEvent } from '#spartacus/checkout/root';
GTM-Configuration:
provideConfig({
tagManager: {
gtm: {
dynamicConfiguration: true,
// TODO: Add events for tracking here
events: [
NavigationEvent,
OrderPlacedEvent,
//... (custom Events)
],
debug: true,
},
},
} as TmsConfig),
Does anybody know what im doing wrong?
I've faced a similar problem. The reason was that some feature module was referenced before the #spartacus/core and it messed up the Config type augmentation.
You need to check if some feature module doesn't get imported before #spartacus/core. For instance in app.module.ts.
I'm implementing a simple app based on the UserIterationCapacity using a Rally.app.TimeboxScopedApp.
Now I want to specify a couple of settings as App settings and found the developer tutorial for this: https://help.rallydev.com/apps/2.1/doc/#!/guide/settings
But I just cant get it working. Whenever I try to fetch a setting my code stops without any warnings.
I've implemented the following:
config: {
defaultSettings: {
hoursPerSp: 6,
decimalsOnHoursPerSp: 1
}
},
getSettingsFields: function() {
return [
{
name: 'hoursPerSp',
xtype: 'rallynumberfield'
},
{
name: 'decimalsOnHoursPerSp',
xtype: 'rallynumberfield'
}
];
},
Now I'm trying to use
this.getSettings('hoursPerSp');
but unfortunately it is not working.
Thank you in advance
Problem solved.
I needed to keep track of my scope, i.e., I needed to pass in the this variable to my renders.
My Durandal application's startup logic in shell.js requires sending the user to one of two possible views depending on some conditional logic. Basically, if certain options have not previously been selected I'll send them to a Setup page, otherwise I'll send them to the normal start page.
Previously, in Durandal 1.x I would just pass a string indicating the starting module when calling activate. But in Durandal 2.x that has been deprecated.
So first, I'm wondering what is the recommended way to do this from the standpoint of the routes array? Should I just register both routes as if neither is the start module (like below) then conditionally add a another route to the array with the default route of ''?
{ route: "setup", moduleId: "setup", title: "Setup", nav: false },
{ route: "Students", moduleId: "students", title: "Students", nav: false }
The second part of my question involves how to handle the need to make a call to a web service as part of my conditional logic for determining which module is the start module. My startup logic involves checking the local storage of the browser, but sometimes I'll also need to make an ajax request to the server to get a bit of information.
My understanding is that router.activate() is a promise. Can I actually just create my own promise and resolve it by calling router.activate() after the ajax call has completed? Or is there another way I'll need to handle that? Sample code for how I was thinking I might handle this:
var deferred = $.Deferred();
//Setup and conditional logic here
var routes = setupRoutes();
$.get('/api/myStartupEndpoint')
.done(function(results) {
//check results and maybe alter routes
deferred.resolve(router.map(routes).activate());
});
return deferred.promise();
Does that make sense? I'm still converting my app over to Durandal 2.0.1 so I haven't been able to try this yet, but regardless of whether it does or not I want to find out what the recommended approach would be in this scenario.
The way I'd do it is this - actually I think it's similar to how you're already thinking, so I hope it makes sense:
In your main.js, set your application root to the same module, no matter the circumstances. Since one of the main features of D2 is child routers, I'd suggest using the module name "root" for your application root, as it makes it easier to distinguish from "shell" modules (which I use for setting up child routers):
app.start().then(function () {
app.setRoot("root", "entrance");
});
In your root module, setup the routes as you have described:
{ route: "setup", moduleId: "setup", title: "Setup", nav: false },
{ route: "students", moduleId: "students", title: "Students", nav: false }
When your root module activates, check if the user has been setup or not. Use the result of that check to work out if you want the user to be sent to the setup page, or the students page. Note however that you must activate your router before redirecting; you can use $.when to help you here:
var checkUserSetup = function () {
var deferred = $.Deferred();
// check local storage, fire off ajax request, etc.
// resolve the deferred once you know if the user is setup or not
deferred.resolve(false);
return deferred.promise();
};
root.activate = function() {
mapRoutes();
var deferred = $.Deferred();
$.when(checkUserSetup(), router.activate()).done(function(isUserSetup) {
if (isUserSetup) {
router.navigate("students");
} else {
router.navigate("setup");
}
deferred.resolve();
});
return deferred.promise();
}
Hopefully this also answers the second part of your question; but just in case - yes, you can return a promise from the activate method, and durandal will "block" until you've resolved that promise. However, note that the router's activate method also returns a promise - so your code won't quite work. You're resolving your deferred with another deferred; you'd need to do something more like this:
root.activate = function() {
var deferred = $.Deferred();
//Setup and conditional logic here
var routes = setupRoutes();
$.get('/api/myStartupEndpoint')
.done(function(results) {
//check results and maybe alter routes
//don't resolve the deferred until the router has completed activation
router.map(routes).activate().done(deferred.resolve);
});
return deferred.promise();
}
Hope that helps.
I have a question regarding the show event.
in my application I'm handling the painted event of my panel like this:
Ext.define('mvcTest.controller.Test', {
extend: 'Ext.app.Controller',
config: {
refs: {
panel: '#testpanel'
},
control:{
panel: {
painted: 'onPainted'
}
}
},
onPainted: function(){
alert('painted');
}
});
the docu say's, that there is also a "show" event, but it get not fired at all:
Ext.define('mvcTest.controller.Test', {
extend: 'Ext.app.Controller',
config: {
refs: {
panel: '#testpanel'
},
control:{
panel: {
show: 'onShow'
}
}
},
onShow: function(comp, obj){
alert('show');
}
});
why this does not work?
i know, alerting is the wrong way, but that's not the question.
thanks,
mike
It seems that there's no mistake in your controller. The key reason may lie in another part of your application but ... ok, according to my experience:
painted event straight-forward. Everytime your view is really rendered on the screen, painted fired up. (Note: painted event fires BEFORE the child components of your view are totally rendered. In another word, painted first, DOM generation second.)
show event does NOT necessarily fire up, especially for the initialization time of your view. show event is something fired up when you firstly somehow hide your view, and show it later.
Just experience, may be variant. But hope it might be helpful for you.
You can't handle 'painted' event in controller, because it is not bubbled up to it.
From sencha docs: This event is not available to be used with event delegation. Instead 'painted' only fires if you explicily add at least one listener to it, due to performance reason.
You can handle it by defining a listener in you panel.
Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.Panel',
config: {
},
listeners: {
painted: function (element, options) {
console.log("I've painted");
}
}
});
But 'show' event can be handled in controller. Check if another part of your application see that controller.
(Have you provided reference to your controller? Is the id of your panel is right?)
I know this is an old thread, but someone might find it useful:
Sencha does not initially fire the event 'show' and 'painted'.
You need to trigger it initially.
Use this code snippet to listen to the events from the controller:
Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.Panel',
config: {
},
listeners: {
painted: function (element, options) {
this.fireEvent('painted', [element, options])
}
}
});
I'm following the ExtJS4.0 MVC Application Architecture walk through and modifying it to my own project as I go to make sure I get things right. So far it's working perfectly. I've just completed the 'Defining a View' section and I'm about to start the 'Controlling the grid' section. Before I do, I want to remove the console.log code as I don't want or need it for my own project. I find I can replace it with an alert message but can't remove it all together without generating an error against ext-all-debug.js.
Here's my functioning code on the controller and the error it's generating after I remove the consol.log function. In the example doc, it's AM.controllers.list.
Ext.define('ChatAgent.controller.queues', {
extend: 'Ext.app.Controller'
, views: [
'queue.list'
]
, init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
}
, onPanelRendered: function() {
console.log('The panel was rendered');
}
});
The error it generates is:
'fireFn' is null or not an object
All I've removed is:
onPanelRendered: function() {
console.log('The panel was rendered');
}
So why the error???
You need to get rid of the event listener as well. When the render event fires it is trying to call onPanelRendered which doesn't exist anymore.
If you aren't listening for any events, you don't even need to have that entire this.control block. Comment this out and see what happens.
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});