With Backbone.Forms is there a way to set the select editor option after loading a collection - backbone.js

I have a form with a select editor type which uses a collection, but I have not found any way of setting the selected option after the data is loaded. I have not found anything in the documentation or any examples online.
...
country: {
title: 'Country',
type: 'Select',
options: function (callback) {
var result = [];
var states = new Countries();
states.fetch({
success: function (collection) {
_.each(collection.models, function (model) {
result.push({ 'val': model.get('id'), 'label': model.get('name') });
});
callback(result);
}
});
},
validators: ['required']
},
...

you can use
form.getEditor('country').setValue('YourVal')

Related

Can't conditionally render view marionette

I can't figure out how to use a function to decide which child view to render in marionette. It seems like it should be pretty simple based on the documentation here: https://marionettejs.com/docs/master/marionette.collectionview.html#collectionviews-childview
I found that page from the composite view docs which inferred that using a function to define a childView should be the same for collection and composite views https://marionettejs.com/docs/master/marionette.compositeview.html#compositeviews-childview)
However, with the following code I am getting the error message "Uncaught TypeError: view.on is not a function." My code is below:
var Backbone = require('backbone');
var Marionette = require('backbone.marionette');
var ToDoModel = require('./models/todo');
var ToDo = Marionette.LayoutView.extend({
tagName: 'li',
template: require('./templates/todoitem.hbs')
});
var TodoList = Marionette.CompositeView.extend({
el: '#app-hook',
template: require('./templates/todolist.html'),
childView: function(item) {
return ToDo;
},
childViewContainer: 'ul',
ui: {
assignee: '#id_assignee',
form: 'form',
text: '#id_text'
},
triggers: {
'submit #ui.form': 'add:todo:item'
},
collectionEvents: {
add: 'itemAdded'
},
modelEvents: {
invalid: 'itemInvalid'
},
onAddTodoItem: function() {
this.model.set({
assignee: this.ui.assignee.val(),
text: this.ui.text.val()
});
if (this.model.isValid()) {
var items = this.model.pick('assignee', 'text');
this.collection.add(items);
}
},
itemAdded: function() {
this.model.set({
assignee: '',
text: ''
});
this.ui.assignee.val('');
this.ui.text.val('');
},
itemInvalid: function() {
console.log('this item is invalid!')
}
});
var todo = new TodoList({
collection: new Backbone.Collection([
{assignee: 'Scott', text: 'Write a book about Marionette'},
{assignee: 'Andrew', text: 'Do some coding'}
]),
model: new ToDoModel()
});
todo.render();
Why isn't the ToDo view being rendered?
It appears as if you are using an older version of Marionette (LayoutView for example was removed in version 3) and referencing the documentation for the newest version (currently 3.5.1).
In older versions of Marionette, childView as a function is not supported, instead you should use getChildView
So, the relevant portion of your code should look like:
var TodoList = Marionette.CompositeView.extend({
...
getChildView: function(item) {
return ToDo;
},
...
});

BackboneJS fetch collection based on parameters

I want to display multiple musical artists based on the genre in a view. So, first of all I have my menu tabs:
<a data-name="hiphop" class="genre">HipHop</a>
<a data-name="rock" class="genre">Rock</a>
<a data-name="alternative" class="genre">Alternative</a>
<a data-name="jazz" class="genre">Jazz</a>
then my genre.js contains:
Genres.Collection = Backbone.Collection.extend({
url: function() {
return 'path to my json';
},
parse: function(response, genre){
return response.data.genres[genre];
// when I do: return response.data.genres.rock;
// I get all artists from the genre "rock".
// but I want the response to be based on the variable "genre"
}
});
then, in my mainView.js:
events: {
'click .genre' : 'genre'
},
genre: function(event, genre){
event.preventDefault();
// get the clicked genre
var genreName = $(event.target).data('name');
var genresCollection = new Genres.Collection({genre:genreName });
genresCollection.fetch();
this.insertView('.genres', new Genres.View({collection: genresCollection}));
},
but no matter which genre I click, I get an empty Collection. can someone tlel me what I'm doing wrong here?
Many thanks!
Options are not stored by default, but you can override your initialize method to provide this functionality. You would then use this stored value in your parse method :
Genres.Collection = Backbone.Collection.extend({
url: function() {
return 'path to my json';
},
initialize: function(opts) {
opts = opts || {};
this.genre = opts.genre || 'rock';
},
parse: function(response){
return response.data.genres[this.genre];
}
});
You need to define a success callback. Try:
var genresCollection = new Genres.Collection();
genresCollection.fetch({
data: {
genre: genreName
},
success: (function (coll_genres) {
console.log(coll_genres.toJSON());
}),
error: (function (e) {
console.log(e);
})
});

create/update user story using rally app sdk

Until now, I have been querying the data stores using Rally App SDK, however, this time I have to update a story using the js sdk. I tried looking up for examples for some sample code that demonstrates how the App SDK can be used to update/add values in Rally. I have been doing CRUD operations using Ruby Rally API but never really did it with the app sdk.
Can anyone provide some sample code or any link to where I could check it out?
Thanks
See this help document on updating and creating reocrds. Below are examples - one updates a story, the other creates a story. There is not much going on in terms of UI: please enable DevTools console to see console.log output.
Here is an example of updating a Defect Collection on a User Story:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
console.log("launch");
Rally.data.ModelFactory.getModel({
type: 'User Story',
success: this._onModelRetrieved,
scope: this
});
},
_onModelRetrieved: function(model) {
console.log("_onModelRetrieved");
this.model = model;
this._readRecord(model);
},
_readRecord: function(model) {
var id = 13888228557;
console.log("_readRecord");
this.model.load(id, {
fetch: ['Name', 'Defects'],
callback: this._onRecordRead,
scope: this
});
},
_onRecordRead: function(record, operation) {
console.log('name...', record.get('Name'));
console.log('defects...', record.get('Defects'));
if(operation.wasSuccessful()) {
//load store first by passing additional config to getCollection method
var defectStore = record.getCollection('Defects', {
autoLoad: true,
listeners: { load: function() {
//once loaded now do the add and sync
defectStore.add({'_ref':'/defect/13303315495'});
defectStore.sync({
callback: function() {
console.log('success');
}
});
}}
});
}
},
});
Here is an example of creating a user story, setting a project and scheduling for an iteration:
Ext.define('CustomApp', {
extend: 'Rally.app.TimeboxScopedApp',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
fieldLabel: 'Select an Iteration:',
labelWidth: 100,
width: 300
},
addContent: function() {
this._getIteration();
},
onScopeChange: function() {
this._getIteration();
},
_getIteration: function() {
var iteration = this.getContext().getTimeboxScope().record.get('_ref');
console.log('iteration',iteration);
if (!this.down('#b2')) {
var that = this;
var cb = Ext.create('Ext.Container', {
items: [
{
xtype : 'rallybutton',
text : 'create',
id: 'b2',
handler: function() {
that._getModel(iteration);
}
}
]
});
this.add(cb);
}
},
_getModel: function(iteration){
var that = this;
Rally.data.ModelFactory.getModel({
type: 'UserStory',
context: {
workspace: '/workspace/12352608129'
},
success: function(model) { //success on model retrieved
that._model = model;
var story = Ext.create(model, {
Name: 'story 777',
Description: 'created via appsdk2'
});
story.save({
callback: function(result, operation) {
if(operation.wasSuccessful()) {
console.log("_ref",result.get('_ref'), ' ', result.get('Name'));
that._record = result;
that._readAndUpdate(iteration);
}
else{
console.log("?");
}
}
});
}
});
},
_readAndUpdate:function(iteration){
var id = this._record.get('ObjectID');
console.log('OID', id);
this._model.load(id,{
fetch: ['Name', 'FormattedID', 'ScheduleState', 'Iteration'],
callback: function(record, operation){
console.log('ScheduleState prior to update:', record.get('ScheduleState'));
console.log('Iteration prior to update:', record.get('Iteration'));
record.set('ScheduleState','In-Progress');
record.set('Iteration', iteration);
record.set('Project', '/project/12352608219')
record.save({
callback: function(record, operation) {
if(operation.wasSuccessful()) {
console.log('ScheduleState after update..', record.get('ScheduleState'));
console.log('Iteration after update..', record.get('Iteration'));
}
else{
console.log("?");
}
}
});
}
})
}
});

how to listen to array submodel's value change

I have a model define like below.
var A = Backbone.Model.extends({
initialize: function(){
this.on('change:users.name',this.onUserNameChanged)
},
onUserNameChanged: function(){ alert('name changed')
});
var a = new A ({
id:1,
name:'test',
users:[
{
id:2,
name:'u1'
},
{
id:3,
name:'u4'
}
]
})
I want add event on the each user name change in Model define.
I have no idea to do this.It's seems hard to me.
It seems that you can't get change events by manipulating Backbone model array members as is described here:
backbone-js-set-model-array-property
Your best option is to set the whole array and listen to a change:users event or even better - come up with a different model that has a Backbone collection for users that will get the event when manipulated:
var A = Backbone.Model.extend({
initialize: function (options) {
_.extend(this, options);
}
});
var Users = Backbone.Collection.extend({
initialize: function () {
this.on('change:name', function () {
alert('name changed');
});
}
});
var a = new A({
id: 1,
name: 'test',
users: new Users([{
id: 2,
name: 'u1'
}, {
id: 3,
name: 'u4'
}])
});
a.users.get('2').set('name', 'u2');

Asscociating a store with Ext.menu.Menu

I am new to extjs.I want to associate a store on selecting a menu item from Ext.menu.Menu. I am using extjs 4.1.0. I searched on the net even went through sencha doc but I couldn't find any way to achieve this.
Is there some way to achieve it?
Thanks in advance.
I'm using a menu with a store in a project. Here's an example:
Ext.define("Ext.ux.menu.DynamicMenu", {
extend: "Ext.menu.Menu",
alias: 'widget.dynamicmenu',
loaded: false,
loadMsg: 'Loading...',
store: undefined,
icon: '',
constructor: function (config) {
var me = this;
Ext.apply(me, config);
me.callParent();
},
initComponent: function () {
var me = this;
me.callParent(arguments);
me.on('show', me.onMenuLoad, me);
listeners = {
scope: me,
load: me.onLoad,
beforeload: me.onBeforeLoad
};
me.mon(me.store, listeners);
},
onMenuLoad: function () { var me = this; if (!me.store.loaded) me.store.load(); },
onBeforeLoad: function (store) { this.updateMenuItems(false); },
onLoad: function (store, records) { this.updateMenuItems(true, records); },
updateMenuItems: function (loadedState, records) {
var me = this;
me.removeAll();
if (loadedState) {
me.setLoading(false, false);
Ext.Array.each(records, function (record, index, array) {
me.add({
text: record.get('DisplayName'),
data: record,
icon: me.icon
});
});
me.store.loaded = true;
}
else {
me.add({ width: 75, height: 40 });
me.setLoading(me.loadMsg, false);
}
me.loaded = loadedState;
}
});
I found this one on the sencha forums if IIRC, but can't find the link anymore. I made some tweaks for icons etc, ...
On the Ext.Array.each(records, ....
You'll need to define your own logic, It's depending on your model. My model has a DisplayName which I use to show as text. I also stock my record in a data property I made in the menu item. You're completely free there.
Good luck!

Resources