How do you do anonymous classes in Coffeescript? - backbone.js

I have a working coffeescript/backbone idiom that looks like this:
SidebarWidgets = ((() ->
SidebarWidgets = { }
class SidebarWidgetPrototype extends Backbone.View
initialize: (options) ->
#template = $(options.templateId).html()
render: () ->
$(#el).html(_.template(#template, #model.toJSON()))
#el
class SidebarWidgets.user extends SidebarWidgetPrototype
class SidebarWidgets.shoppingcart extends SidebarWidgetPrototype
class SidebarWidgets.messages extends SidebarWidgetPrototype
SidebarWidgets
)())
class Sidebar extends Backbone.View
views: ['user', 'shoppingcart', 'messages']
initialize: (options) ->
#subviews = { }
_.each(#views,(v) =>
subviews[v] = news SidebarWidgets[v](
model: cxDatasets[v]
id: 'sidebar-' + v
templateId: '#sidebar-' + v + 'template'
)
)
render: () ->
$(#el).html()
_.each(#views, (v) =>
$(#el).append(#subview(v).render())
)
The intent of this idiom is to provide a list of backbone views that the sidebar view will then incorporate, while providing the opportunity (but not the necessity) to override or enhance one or more methods of a widget.
The thing that irks me is that, for those views that do not need modification, they still need to be named explicitly by the class syntax of Coffeescript.
Is there a way to create an anonymous class with the Coffeescript syntax? Can you say something like (the following is pseudocode):
thisclass = extend BackboneView
initialize: (options) ->
If so, how?

thisclass = class extends BackboneView
initialize: (options) ->

Related

how to call function from Class A in different class B function in extjs4

Note:- i want to call ClassA function "deleteEntryInternal" in another class B within "afterRequest function. how can i call this function in other class function.
My code is Below
//here is my Class A
Ext.define('WebCare.UI.OtherServicesEditor', {
extend: 'Ext.WebCare.UI.BaseEditor',
_otherservicesGrid: null,
alias: 'widget.otherserviceseditor',
title: 'Other Services',
defaultType: 'textfield',
id: 'otherservicesEditor',
deleteEntryInternal: function (isDelete) {
this.disableForm();
var self = this;
var selection = self._otherservicesGrid.getSelectionModel().getSelection();
if (selection.length > 0) {
if (isDelete) {
selection[0].data.IsDelete = true;
}
this.deleteServerRecord(selection[0].data, function () { });
vent.trigger(otherServicesStore.storeId, selection[0].data);
}
}
To call this method, you need to obtain instance of this class. And then you can call methods in that class.
1.You can get an instance of Ext.app.Controller by
var controllerInstance = appName.app.getController('appName.controller.controllerName');
controllerInstance.methodToCall();
where appName is name of your Extjs App.
2.If your class is a view which is already rendered , you can get its instance by -
var viewInstance = Ext.getCmp(viewId);
viewInstance.methodToCall();
where viewId is id of your view.
3. Static class -
You can call methods of static class directly like if class MyStaticClass is static class , you can call its methods like -
MyStaticClass.methodToCall();
It is never a good idea to cross reference class methods on any way. Although Harshal's methods will work it is just very bad app design. If your class needs to react to an event what is happening in another class then why don't you just fire an event in class A and set up a listener in class B?

Why .filter() in Marionette.CollectionView doesn't work?

Why .filter() in Marionette.CollectionView doesn't work?
It just isn't fired.
P.S. Collection has one element.
1 file:
documents = new Collections.Documents
documents.fetch().done =>
#getRegion('certificates').show(new Views.CertificatesCollectionView(documents))
#getRegion('diplomas').show(new Views.DiplomasCollectionView(documents))
2 file:
class Views.DiplomasCollectionView extends Marionette.CollectionView
initialize: (#collection) ->
console.log 'intzd'
childView: Views.DocumentItemView
filter: (document_model) ->
console.log 'fitr'
document_model.is_diploma()
try with:
#getRegion('diplomas').show(new Views.DiplomasCollectionView(collection: documents))
and
class Views.DiplomasCollectionView extends Marionette.CollectionView
childView: Views.DocumentItemView
filter: (document_model) ->
console.log 'fitr'
document_model.is_diploma()

Dynamically set backbone collection url returns models without attributes

I have a backbone mobile application that is tied to a Rails web service. All models of other objects are loaded and displayed correctly, but this particular one does not. The issue I am having is that Item gets created, but does not load the attributes. I have confirmed correct json output of the rails api. The difference between this collection and all other collections of this application is that this collection has a parentID that must be used in the url to load the correct items (category_id).
Now... the funny thing is that if I remove the {category_id: options.attributes[0].category_id} argument to the constructor call of ItemCollectionView and hard code a category_id directly into the url, it works! (however I need to assign this dynamically based on the category of the parent view.
Here are my classes:
export class ItemCollectionView extends Backbone.View {
public template: string;
public collection: itemsImport.Items;
constructor(options?: Backbone.ViewOptions){
this.collection = new itemsImport.Items({category_id: options.attributes[0].category_id});
super(options);
}
...
public addOne(item: itemImport.Item): void{
var view: itemItemImport.ItemItemView = new itemItemImport.ItemItemView({el: this.el, model: item});
//Breakpoint right here shows that item.attributes.id = undefined
view.render();
}
}
export class Items extends Backbone.Collection {
public url: string;
constructor(attributes?: any, options?: any){
this.url = 'http://localhost:3000/categories/' + attributes.category_id + '/items';
this.model = itemImport.Item;
super(attributes, options);
}
}
In my debugging I can confirm that:
options.attributes[0].category_id == 1;
and
this.url == 'http://localhost:3000/categories/1/items';
and the response from that url is:
[{"id":1,"category_id":1,"title":"Item 1","description":null,"active":true,"comment":null,"extra":null,"deleted":"0","url":"http://localhost:3000/categories/1/items/1.json"},{"id":2,"category_id":1,"title":"Item 2","description":null,"active":true,"comment":null,"extra":null,"deleted":"0","url":"http://localhost:3000/categories/1/items/2.json"}]
which you can see is a correct json response.
So my question is: What am I doing wrong? || What is the correct way to dynamically pass variables into collections to set the correct url at runtime?
Thank you for your help
Define url as function like in second case here
var Notes = Backbone.Collection.extend({
url: function() {
return this.document.url() + '/notes';
}
});
And check network tab if you really load correct url.
The other answer selected will work if using javascript, but if using TypeScript the compiler will complain that url must be a property, not a method. The solution I found (which will work in javascript as well) is to set the url argument on the fetch() method of the collection like below
export class ItemCollectionView extends Backbone.View {
public template: string;
public collection: itemsImport.Items;
constructor(options?: Backbone.ViewOptions){
this.collection = new itemsImport.Items({category_id: options.attributes[0].category_id});
super(options);
}
public initialize(options?:any): void {
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
this.collection.fetch({url: this.collection.seturl(options.attributes[0].category_id)});
}
...
}
I hope this helps future users looking for this functionality in Backbone
It is possible to define a dynamic url property to your Backbone model in your Typescript code. This would be better than using the url parameter in all your calls to fetch().
You could either do it using an ECMAScript 5 getter:
export class Items extends Backbone.Collection {
get url(): string {
return '/categories/' + this.get('category_id') + '/items';
}
constructor(attributes?: any, options?: any){
this.model = itemImport.Item;
super(attributes, options);
}
}
or by setting it directly on the prototype:
export class Items extends Backbone.Collection {
constructor(attributes?: any, options?: any){
this.model = itemImport.Item;
super(attributes, options);
}
}
Items.prototype.url = function() {
return '/categories/' + this.get('category_id') + '/items';
};
The second solution will work on all browser.

How to get trigger to listen properly

I am having a hard time getting my trigger to respond properly. I have plenty that are working but one of them isn't and I can't understand why.
Here is my AppController class
class ProjectOrder.View.AppController extends Backbone.View
initialize: ->
#promptOfficeSearch()
promptOfficeSearch: ->
officeSearch = new ProjectOrder.View.OfficeSearch
officeSearch.on 'createOffice', #promptOfficeCreate
officeSearch.on 'createTicket', #promptTicketCreate
officeSearch.on 'accountAndTicketExist', #killProcessAccountExists
promptOfficeCreate: (serial) ->
#officeModel = new ProjectOrder.Model.OfficeModel()
#officeModel.set('serial_number', serial)
officeCreate = new ProjectOrder.View.OfficeCreator({model: #officeModel})
officeCreate.on 'createTicketOffAccount', #promptTicketCreate
promptTicketCreate: (model) ->
console.log 'promptTicketCreate'
model = model || #officeModel
ticketModel = new ProjectOrder.Model.TicketModel()
new ProjectOrder.View.TicketCreator({ticketModel: ticketModel, officeModel: model})
killProcessAccountExists: (ticket_id) ->
msg = document.createElement 'div'
msg.className = 'account-exists-msg'
msg.innerHTML = "Account already exists. Redirecting to ticket #{ticket_id}..."
$('#create-order-div').append(msg)
setTimeout((->
window.location = "/pto/#{ticket_id}"
), 2000)
All of the triggers from the officeSearch object in the promptOfficeSearch function work properly. They are all triggered as follows, respectively:
#trigger 'createOffice', serial
#trigger 'createTicket', data.model[0]
#trigger 'accountAndTicketExist', data.model
But with the officeCreate object in the promptOfficeCreate, it does not respond to the createTicketOffAccount event which is registered in the submitOffice ajax success callback in my OfficeCreator class:
class ProjectOrder.View.OfficeCreator extends Backbone.View
template: _.template($("#OfficeCreator").html())
id: 'office-creator'
events:
'click .submit' : 'submitOffice'
initialize: ->
#render()
render: ->
#$el.html(#template(#model.toJSON()))
$('#create-order-div').append(#$el)
submitOffice: ->
#setModelData()
#model.save(null,{
success: (model) =>
#trigger 'createTicketOffAccount', model
##$el.remove()
error: ->
alert 'error'
})
setModelData: ->
#model.set({
office_name: $('#office').val()
doctor_name: $('#doctor').val()
emr: $('#has-emr').is(':checked')
forms_builder: $('#has-forms').is(':checked')
iehr: $('#has-iehr').is(':checked')
clipboard: $('#has-clip').is(':checked')
specialty_id: $('#specialty').val()
})
any ideas why my trigger is not working?
I think you need fat arrows on all the methods in your AppController class.
When this event fires:
officeSearch.on 'createOffice', #promptOfficeCreate
the promptOfficeCreate function gets invoked as a normal function as opposed to a method bound to your controller instance as this, so when this happens:
officeCreate.on 'createTicketOffAccount', #promptTicketCreate
#promptTicketCreate is undefined and the event binding doesn't wire up properly.

model.toJSON is not a function using Backbone

This :
#model
Returns :
Object { type="conjugation", verb="ser", yo="soy", more...}
But when I try :
#model.toJSON()
I get :
TypeError: this.model.toJSON is not a function
I am trying to eventually complete this line :
$(#el).html(#template(#model.toJSON() ))
So that I can render this object in a Show with my template.
Any recommendations?
Update
Persuant the comments. I have this as a model, but I can see now how they're are not related.
class AiProject.Models.Verb extends Backbone.Model
paramRoot: 'verb'
I'm going to try and instantiate this type of verb.
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb
#verb = options.words
And then back to my View :
class AiProject.Views.Questions.ConjugationView extends Backbone.View
template: JST["backbone/templates/questions/conjugation"]
render: ->
$(#el).html(#template(#model.toJSON() ))
Still get the same error though..
It looks like you're setting your model correctly at first, then overwriting it with the value options.words.
Instead of this:
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb
#verb = options.words
Try this:
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb(options.words)
That creates your model and passes in options.words to be set as the model's attributes.

Resources