SDK2: Using updateSettings() - javascript

I'm trying to save settings for my app. It looks like it should be simple, but this does not seem to work:
Ext.define('MyApp', {
extend: 'Rally.app.App',
componentCls: 'app',
...
launch: function() {
var settings = this.settings;
console.log('settings', settings);
if (!settings.count) {
settings.count = 1;
} else {
settings.count++;
}
this.updateSettingsValues(settings);
... rest of App ...
}
Always show settings as "count: 1", never increments, even as I reload multiple times. I have tried this both in and outside of Rally. I am using SDK 2.0p5.
What am I doing wrong?

Ok, I took a look at the source and I figured it out...need to pass a "options" object with "settings" as a subobject. This is technically in the doc, but because it was not explained I just did what looked obvious. I think the doc needs to be update to make this more clear, it also does not speak about the completion functions you can pass in with options...
launch: function() {
var settings = this.settings;
var options = { settings: settings };
console.log('settings', settings);
if (!settings.count) {
settings.count = 1;
} else {
settings.count++;
}
this.updateSettingsValues(options);
... rest of App ...
}

Related

How to access options inside apos.define?

apostrophe-workflow has the following:
public/js/user.js
apos.define('apostrophe-workflow', {
[...]
construct: function(self, options) {
self.locales = options.locales;
self.locale = options.locale;
[...]
I searched quite a while and did not manage to find the reason why this construct method has access to the options object. I tried browserCall but am not sure how to use this properly.
My assets are pushed using pushAsset, too. But they do not have access to the options after apos.create.
Edit: Example scenario:
A simple module that pushes one script to the browser.
module/index.js
construct: function(self, options) {
self.pushAsset('script', 'name', {when: 'always'});
}
And takes one option.
app.js
modules: {
'module': {
option: 'Option'
}
}
The script should use this option on construct.
module/public/js/script.js
apos.define('module-script', {
construct: function(self, options) {
console.log(options.option); // Print 'Option' to console.
}
});
Another module will call apos.create('module-script').
I hope it's clear.
You can solve (at least) this two ways depending on the structure you want.
1. Explicit browser options
You can explicitly pass options to the browser from your modules configuration by wrapping them in a browser object from the root of the module's config.
in lib/modules/layout-widgets/index.js
module.exports = {
extend: 'apostrophe-widgets',
label: 'Layout',
browser: {
coolArray: [3, 2, 1]
}
}
This will get merged into the options passed to your browser side JS of the module automatically.
then in /lib/modules/layout-widgets/public/js/always.js
apos.define('layout-widgets', {
extend: 'apostrophe-widgets',
construct: function (self, options) {
self.play = function ($widget, data, options) {
console.log(self.options.coolArray);
}
}
});
2. Super'ing getCreateSingletonOptions
If you don't like the syntax of separating your browser options from your main options, you can always override the method responsible for teeing up the browser side module's default options by copying it, invoking it, and adding on to it.
in lib/modules/layout-widgets/index.js
module.exports = {
extend: 'apostrophe-widgets',
label: 'Layout',
coolArray: [3,2,1],
construct: function(self, options) {
// copy the method
var superGetCreateSingletonOptions = self.getCreateSingletonOptions;
// redefine it
self.getCreateSingletonOptions = function (req) {
// invoke the original method and save the result
var browserOptions = superGetCreateSingletonOptions(req);
// add on to the default results with whatever you want
browserOptions.coolArray = self.options.coolArray;
browserOptions.somethingElse = 'hey this is fun';
return browserOptions;
};
}
};
then, again, in /lib/modules/layout-widgets/public/js/always.js
apos.define('layout-widgets', {
extend: 'apostrophe-widgets',
construct: function (self, options) {
self.play = function ($widget, data, options) {
console.log(self.options.coolArray);
console.log(self.options.somethingElse);
}
}
});

ember.js discard created model if not saving

I have followed the 3 parts of the tutorial here and everything is working fine, with one exception. When I go to the "Add the book" page and then navigate to "List books" without saving, the list of books is extended by an empty item. I suspect that the reason is the following code, where the new model is created before saving and not removed if not saving the form. Any ideas how to fix this?
Embertest.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.get('store').createRecord('book');
},
actions: {
create: function() {
var newBook = this.get('currentModel');
newBook.save();
this.transitionTo('books');
}
}
});
From http://emberjs.com/api/classes/Ember.Route.html#method_deactivate
Add a deactivate function on your route. This is called before exiting this current route. So you can roll back the record you just created in the model like this:
model: function(params) {
return this.get('store').createRecord('book');
},
deactivate: function() {
this.currentModel.rollback();
},
I solved this by attaching an action to destroy the record to the willTransition event as below. Would anyone comment if this is the right approach?
Embertest.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.get('store').createRecord('book');
},
actions: {
willTransition: function() {
if (this.currentModel.get('isNew')) {
this.get('currentModel').deleteRecord();
};
},
create: function() {
var newBook = this.get('currentModel');
newBook.save();
this.transitionTo('books');
}
}
});

Adding new feature to discourse

I am trying to add an WatchList feature in the existing code discourse ember rails application
I have addded the following code
Discourse.Route.buildRoutes(function() {
var router = this;
this.resource('watchLists', { path: '/watch_lists' }, function() {
this.resource('watchList', {path: ':watch_list_id'});
});
});
In the ember Controller
Discourse.WatchListsController = Discourse.ObjectController.extend({});
In the ember model
Discourse.WatchList = Discourse.Model.extend({});
Discourse.WatchList.reopenClass({
find: function() {
jQuery.getJSON("watch_lists").then(function(json) {
var watch_lists = json.watch_lists.map(function(attrs) {
return Discourse.WatchList.create(attrs);
});
});
In the ember view js
Discourse.WatchListsView = Ember.View.extend({});
In ember route js
Discourse.WatchListsRoute = Discourse.Route.extend({
model: function() {
return Discourse.WatchList.find();
}
});
When i renderring the handlebars template I am getting an WatchListsController object withot the data we have got from the ajax.
Can any body point out where i am doing wrong.
I see two possible problems.
First, you probably want WatchListsController to extend Discourse.ArrayController, not Discourse.ObjectController.
Second your reopen block is not valid JavaScript in the example code that you posted. I count four { but only two }. You probably want something kind of like this:
Discourse.WatchList.reopenClass({
find: function() {
return jQuery.getJSON("watch_lists").then(function(json) {
return json.watch_lists.map(function(attrs) {
return Discourse.WatchList.create(attrs);
}
});
}
});

Cross referencing of 2 models

I have 2 models which are cross referencing each other. This could look like this:
MainModel:
define(
[ 'durandal/app', 'durandal/plugins/router', 'models/Shell', 'models/EditModel' ],
function (app, router, shell, editModel) {
//...
return {
//...
// This function should be accessible by the EditModel
update: function() {
//...
},
showEditView: function() {
// Initialise the EditModel with some data and show the according view afterwards
editModel.init('set some important stuff here...');
router.navigateTo('#/EditView');
}
//...
};
}
);
EditModel:
define(
[ 'durandal/app', 'durandal/plugins/router', 'models/Shell', 'models/MainModel' ],
function (app, router, shell, mainModel) {
//...
return {
//...
// This function should be accessible by the MainModel
init: function() {
//...
},
showMainView: function() {
// Update the the MainModel with some data and show the according view afterwards
mainModel.update('set new data here...');
router.navigateTo('#/MainView');
}
//...
};
}
);
Unfortunately this is not working. If I load my page on the MainView and call showEditView, the variable editView is known and everything works fine but then the variable mainModel in the EditModel is undefined and therefore the call mainModel.update(...) fails.
Same thing happens if I load my page on EditView but in the "opposite direction" (var mainModel in the EditModel is known, but editModel in the MainModel is undefined).
Is this a known issue and if so: How can i circumvent it?
I also posted this question in Durandals Google Group
Thanks
Check requierejs documentation for circular dependencies http://requirejs.org/docs/api.html#circular.
Circular dependencies are rare, and usually a sign that you might want
to rethink the design. However, sometimes they are needed, and in that
case, use require() as specified above.
For main.js add require as dependency and then explicitly require models/EditModel should do the trick. Either replicate that for the other modules or rethink the design ;-).
define(
[ 'require', 'durandal/app', 'durandal/plugins/router', 'models/Shell', 'models/EditModel' ],
function (require, app, router, shell, editModel) {
//...
return {
//...
// This function should be accessible by the EditModel
update: function() {
//...
},
showEditView: function() {
// Initialise the EditModel with some data and show the according view afterwards
require('models/EditModel').init('set some important stuff here...');
router.navigateTo('#/EditView');
}
//...
};
}
);

using Backbone JS boilerplate & code navigation

a newbe question:
I've downloaded the backbone boilerplate from https://github.com/david0178418/BackboneJS-AMD-Boilerplate it uses require.js and I wonder about the code navigation during development.
Here is my question:
let's say I have 2 views one extend the other like so:
View 1:
define([
'underscoreLoader',
'backboneLoader',
'text!templates/main.html'
],
function (_, Backbone, MainTemplate) {
"use strict";
return Backbone.View.extend({
template:_.template(MainTemplate),
initialize:function () {
this.render();
},
log:function(msg){
console.log(msg);
},
render:function () {
this.$el.append(this.template({}));
return this;
}
});
}
);
View 2:
define([
'underscoreLoader',
'backboneLoader',
'text!templates/other.html',
'views/main-view'
],
function (_, Backbone, MainTemplate,MainView) {
"use strict";
// how would you navigate to MainView (main-view.js)
return MainView.extend({
template:_.template(MainTemplate),
initialize:function () {
this.render();
},
render:function () {
this.log("my message");
this.$el.append(this.template({}));
return this;
}
});
}
);
Now when I develop (I use IntelliJ) I would like to middle click MainView on the extended view and navigate to the code without having to browse the project tree.
Is that possible using this boilerplate? is there a better approach or a better boilerplate?
I would really like Netbeans's navigator to show me all the methods:
var New_Controller = Backbone.View.extend({
el : null, ...
}
But I can't seem to get it to work. Google came up with something for #lends, but I can't even get Backbone.js to get loaded to the code hint cache.
I ended up installing WebStorm (I saw the IDE in all the egghead.io tutorials) to get the navigator to list all methods and properties.
FYI, Aptana Studio and Zend Studio showed nothing like Netbeans. And Eclipse IDE for JavaScript Web Developers only partially (impractical in real life) works; it flattens the entire hierarchy.
I found this to work fine for me:
the Backbone Objects are wrapped with my custom objects, which allows me to navigate code, extend objects and keep multiple files easily.
Here is how:
Object 1
function ItemModel() {
ItemModel.model = (
Backbone.Model.extend({
initialize:function () {
},
defaults:{
name:"item name"
},
log:function(){
console.log("inherited method");
}
})
);
return new ItemModel.model();
}
Object 2
function ItemModel2() {
ItemModel2.model = (
ItemModel.model.extend({
initialize:function () {
},
defaults:{
name:"item name2"
}
})
);
return new ItemModel2.model();
}
and in my app:
var App = {
item:new ItemModel(),
item2:new ItemModel2()
};

Categories

Resources