How to Configure view locals in action as machine - javascript

I am rockie in sails and kick start with action 2(action as machine). I am stuck how to configure view locals in actions 2.
For instance, in standalone action I can configure and add layout to view by the below snippet:
res.view('./pages/coffee/Boss/sell', { layout: 'layouts/layout-boss' })
My question is How can we do the same thing with action as machine(action2) ?
exits: {
success: {
responseType: "view",
viewTemplatePath: './pages/coffee/Boss/listDrink'
//Here I want to configure locals of view
//Specifically, I want to configure layout of the view
},
notFound: {
description: 'The data of drinks are empty',
respondType: 'notFound'
}
},

Looks like you can set any specific parameters in the exits.success call, like the layout or any ejs local variables you might need in the template:
fn: async function (inputs, exits) {
return exits.success({layout: 'layouts/layout-boss', ejsLocalVariable: 'value'});
}
and the exit declaration would just be
exits: {
success: {
responseType: "view",
viewTemplatePath: './pages/coffee/Boss/listDrink'
},
notFound: {
description: 'The data of drinks are empty',
respondType: 'notFound'
}
},

In SailsJS, to apply a layout to a template in an actions2 object you can do the following:
Declare your success exit as usual:
exits: {
success: {
responseType: 'view',
viewTemplatePath: 'pages/hello',
},
},
When returning from your method , add the layout to any any other values that you are passing to your template.
return exits.success({name1:value1, name2:value2, layout: 'layouts/backoffice'});
As far as I understand the layout is another local, and locals are explained here:
https://sailsjs.com/documentation/concepts/views/locals

Related

sailsjs standalone action to view (Sailsjs V1.0.0)

I have a standalone action which I call from my front end via a button click using CloudSDK, I get my value but the action does not redirect to the view. I have specified the responseType as view in my success exit but this does not seem to work.
Button code in page.js file:
clickVerifyBtn: async function(uid) {
await Cloud.userIdVerify(uid);
},
the action
module.exports = {
friendlyName: 'User id verify',
description: '',
inputs: {
uid: {
description: 'Id of the user',
type: 'number'
},
},
exits: {
success:{
responseType: 'view',
viewTemplatePath: 'pages/admin/verification-doc',
}
},
fn: async function (inputs, exits) {
// All done.
var userdoc = await Photo.findOne({ownerId: inputs.uid, isRemoved:false, photoType:0})
var imageSrc = '/images/useruploads/'+userdoc.imageFileName;
return exits.success({imageSrc: imageSrc});
}
};
What is the correct way to achieve this ? Should I submitting my value to the action via the ajax-form component bundled in Sails?
Any help is greatly appreciated.
The action2 returns the variables not to the view directly but to the view's page instance (your_view.page.js) submitted method.

ExtJs Tree loading sequence

Good day.
I am writing a tree control with Ext.tree.Panel, which loads its configuration from external .json file, while data is being loaded as .json from the server.
So, I've got the view like this:
Ext.define('App.tree.TreeView', {
extend: 'Ext.tree.Panel',
...
initFilters: function(cfg) {
/*several this.store.addFilter() based on cfg*/
},
initComponent: function () {
var me = this;
me.cfg = getSomeCfgFromSomewhere();
me.initFilters(me.cfg);
}
});
The store:
Ext.define('Site.widgets.tree.TreeStore', {
extend: 'Ext.data.TreeStore',
...
proxy: {
type: App.cfg.proxy,
reader: { type: 'json', rootProperty: 'data.children' },
format: App.cfg.proxy.urlEnd,
url: App.cfg.treeRoot,
noCache: false
}
lazyFill: true,
rootVisible: true,
root: {
full_path: '/', /*set as idProperty in model*/
'display-name': 'root',
expanded: true
},
});
The problem is: my root is explicitly set in the store, which loads its contents because of expanded: true. But then only these contents are shown in the tree, without the root itself. When filtering is removed, the tre is loaded OK.
Possible reason: from debugging of Sencha code in ext-all-debug.js: view's initComponent is called before the store starts loading the data, therefore it adds filters before the data is loaded, when the root is still empty, and then calls
onNodeFilter: function(root, childNodes) {
var me = this,
data = me.getData(),
toAdd = [];
if (me.getRootVisible()) {
if (childNodes.length) {
toAdd.push(root);
} else {
root.set('visible', false, me._silentOptions);
}
}
...
}
, i.e. the root is set invisible because it is still empty, and only then root's children are loaded.
The question is: is there an initial design mistake in my filters initialisation, and how can I fix it?
Considering that the problem is that view's initComponent is called before the store starts loading the data, I would try:
Calling initFilters inside store load event, like this:
Ext.define('Site.widgets.tree.TreeStore', {
extend: 'Ext.data.TreeStore',
...
proxy: {
type: App.cfg.proxy,
reader: { type: 'json', rootProperty: 'data.children' },
format: App.cfg.proxy.urlEnd,
url: App.cfg.treeRoot,
noCache: false
}
lazyFill: true,
rootVisible: true,
root: {
full_path: '/', /*set as idProperty in model*/
'display-name': 'root',
expanded: true
},
listeners : {
load : function() {
//Call initFilters.
//initFilters should call addFilter just once,
//with array of filters as first parameter,
//to avoid filtering the hole tree more than once!
}
}
});
This approach has a problem, because you have to deal with initFilters cfg parameter scope.
Ok, turned out that part of the answer was just inside the question: I was able to fix this thing by simply overloading onNodeFilter() method inside my store, since I know that I want to always show the root. If anyone could advise anything better - be my guest, please.

Callback function on custom $resource action

I have added a custom action to a $resource:
var myResource = $resource('some/url/:someParam',
{
someParam: '#someParam'
},
{
update: {
method: 'PUT'
}
});
I am attempting to have a function run on completion. According to Angular's documentation, I'd do it in the following way:
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
Yet the following never invokes the success function even though the request is successful:
myResource.update({ someParam: 'a value' }, { myPostData: 'goes here' }, function(a,b) {
// this function never gets invoked
});
The documentation also says this:
The Resource instances and collections have these additional properties:
$promise: the promise of the original server interaction that created this instance or collection.
But this doesn't work either:
myResource.update({ someParam: 'a value' }, { myPostData: 'goes here' }).$promise.then(function() {
// do stuff
});
Am I missing something here? Any help would be greatly appreciated.

Sencha Architect Global Variable as store parameter

I'm very new to Sencha Architect 3.0, I want to set a MyApp.globals variable(initiated at launch method) as the parameter of my store. Like so:
Ext.define('MyApp.store.myCustomer', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Customer',
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
config: {
model: 'MyApp.model.Customer',
storeId: 'myCustomer',
proxy: {
type: 'ajax',
//global variable as parameter
extraParams: {
salesman: MyApp.globals.Salesman
},
url: 'http://localhost:96/OrdApplication/customer_list.php',
reader: {
type: 'json',
rootProperty: 'items'
}
}
}
});
This is my launch method
launch: function() {
MyApp.globals = {
count: 1,
Salesman :0
};
Ext.create('MyApp.view.MainView', {fullscreen: true});
}
});
Although this store is not bound to load with anything on launch,neither with the first view, but its still seems to be loading as i'm getting the following error on launch:
Uncaught TypeError: Cannot read property 'Salesman' of undefined
sencha-touch.js:8619 Uncaught Error: The following classes are not declared even if their files have been loaded: 'MyApp.store.myCustomer'.
how do I handle this issue of not having the store loaded before the declaration of variable takes place. In fact it would be great if someone could tell me to load a store dynamically on button press and fill selectfield with it.

View & store loaded before controller's init

I am building Sencha touch 2.1 application.
In my application I have one global variable which keeps reference of my controller class. This reference is used to execute a controller function on load of one of the store but the problem comes when I deploy this on slow remote server and store's load is fired before this global variable gets reference of controller object. To provide this reference before store's load I tried putting initialization logic in controllers init method
init : function(){
bossController = this.getApplication().getController('Boss');
},
in init method of controller but view & store are loaded before this init is called and hence I get this error:
Cannot call method 'loadMagazines' of undefined
This is my on load listener in store:
listeners:{
load: function( me, records, successful, operation, eOpts ){
bossController.loadMagazines(this, records);
}
}
I tried initializing this variable in app.js launch() method instead of controller's init method but that also didn't work.
Please note both approaches works fine when I put my code in local apache and access it using my chrome browser but they doesn't work when I put it on slow remote server.
EDIT
This is how application flow happens
0. All the models, views, stores & controllers are defined in app.js
Launch function in app.js add main view to the viewport.
Main view creates magazine view and add it to itself.
In initialize method of magazine view, store is crated and loaded.
In load listener of store, controller is used.
This is my view:
Ext.define('myshop.view.MagazinePanel', {
extend : 'Ext.Panel',
requires : [
'myshop.model.MagazinePage',
'myshop.store.MagazineStore',
'Ext.XTemplate',
'Ext.data.Store'
],
alias : 'widget.magazinepanelview',
xtype : 'magazinepanelview',
config : {
layout : 'hbox',
id : 'hc',
scrollable: 'horizontal',
directionLock : true,
masked: {
xtype: 'loadmask',
message: 'Loading'
},
inline: {
wrap: false
},
items : [{
xtype : 'panel',
html : ''
}]
},
initialize: function() {
var me = this;
var myStore = Ext.create('myshop.store.MagazineStore');
myStore.load({
callback: function(records, operation, success) {
me.setMasked(false);
},
scope: this
});
this.callParent();
}
});
and this is the store:
Ext.define('myshop.store.MagazineStore',{
extend:'Ext.data.Store',
requires: [
'myshop.model.MagazinePage',
'Ext.data.proxy.JsonP'
],
config:{
storeId : 'ms',
model:'myshop.model.MagazinePage',
autoLoad :false,
pageSize: 30,
proxy : {
type: 'jsonp',
url: Properties.PORTAL_SERVICE_BASE_URL+'test/categories/list',
callbackKey: 'callback',
startParam: false, //to remove param "start" and making it constant
extraParams: {
start : 0,
_type : 'json'
},
reader: {
type: 'json',
rootProperty: 'categories.data',
totalProperty: 'categories.status.totalCount'
}
},
listeners:{
load: function( me, records, successful, operation, eOpts ){
bossController.loadMagazines(this, records);
}
}
}
});
There are some parts missing in your example code so just a hint/guess. I guess your store has autoLoad property to true and get's therefore loaded as soon as it gets initialized. Turn it of and try something like this.
init : function(){
bossController = this.getApplication().getController('Boss'); // bossController where is this var defined?
// fire a ready event
// or
Ext.StoreMgr.lookup('YourStoreName').load();
}
Or provide more information about the store, who loads it, when it is loaded and in which scope.
Loading data should do controller but not view.
Ext.define("myshop.controller.Boss", {
extend: 'Ext.app.Controller',
config: {
refs: {
magazinePanel: '#hc'
},
control: {
magazinePanel: {
initialize: 'initializeMagazinePanel'
}
}
},
initializeMagazinePanel: function() {
var me = this;
var myStore = Ext.create('myshop.store.MagazineStore', {
listeners:{
scope: this,
load: this.onMagazineStoreLoad
}
});
myStore.load();
},
onMagazineStoreLoad: function(me, records, successful, operation, eOpts) {
this.getMagazinePanel().setMasked(false);
this.loadMagazines(records)
},
loadMagazines: function(records) {
}
});
Couldn't you put your loadMagazines function in the success callback of an explicit load() function in your controller, and disable autoLoad as #sra suggests?
Something like:
//in controller
init: function() {
myStore.load({
callback: function(recs, op, success) {
// do the load magazines thing
}
})
}
I am curious if what I suggested here: getController() doesn't load file and doesn't fire init and lauch helps with this too. You can remove the view and store from app.js and put it in the controller itself. I think that should make the view and store be defined only after the controller is defined.

Categories