I'm traying to migrate my app with Backbone Marionette but I have an error in the routing:
window.App = new Backbone.Marionette.Application
Models: {}
Collections: {}
Views:
Layouts: {}
Routers: {}
layouts: {}
Helpers: {}
init: ->
App.start()
App.main.show(App.layouts.main)
App.addRegions
main: '#container'
App.addInitializer (options) ->
new App.Routers.Profiles()
Backbone.history.start()
$(document).ready ->
App.init()
This is my Router
class App.Routers.Profiles extends Backbone.Marionette.AppRouter
routes:
'profiles/:id': 'show'
show: (id) ->
#profile = new App.Models.Profile(id: id)
view = new App.Views.ProfilesShow(model: #profile)
#profiles = new App.Collections.Profiles(#profile)
#profile.fetch()
App.layout.content.show(view)
This is my View
class App.Views.ProfilesShow extends Backbone.Marionette.ItemView
template: JST['profiles/show']
initialize: ->
#model.on('change', #render, #)
render: ->
$(#el).html(#template(profile: #model))
#
This is my Main Layout
class App.Views.Layouts.Main extends Backbone.Marionette.Layout
template: JST['layouts/main']
regions:
content: '#content'
App.addInitializer ->
App.layouts.main = new App.Views.Layouts.Main()
When I try to show the View in the Layout in the line App.layout.content.show(view), I have a message error: "TypeError: App.layout is undefined". I don't know if I'm doing a good practice.
I found the solution. I hope is the better
The main changes are in the router, I had to add a controller, so the new router is
class App.Routers.Profiles extends Backbone.Marionette.AppRouter
appRoutes:
'profiles': 'index'
'profiles/new': 'new'
'profiles/:id': 'show'
class App.Controllers.Profiles
constructor: ->
#collection = new App.Collections.Profiles()
#collection.fetch()
App.layouts.main = new App.Views.Layouts.Main()
show: (id) ->
profile = #collection.get(id)
view = new App.Views.ProfilesShow(model: profile)
App.main.show(App.layouts.main)
App.layouts.main.content.show(view)
And the new App Init is:
window.App = new Backbone.Marionette.Application
Models: {}
Collections: {}
Views:
Layouts: {}
Routers: {}
layouts: {}
Helpers: {}
Controllers: {}
init: ->
App.start()
App.addInitializer (options) ->
App.addRegions(main: '#container')
controller = new App.Controllers.Profiles
new App.Routers.Profiles(controller: controller)
Backbone.history.start()
$(document).ready ->
App.init()
Related
Currently using photoeditorsdk#4.3.1
With pure JS example, export image works just fine.
window.onload = () => {
const container = document.getElementById('app')
const editor = new PhotoEditorSDK.UI.ReactUI({
container,
license: JSON.stringify(PESDK_LICENSE),
assets: {
baseUrl:'/assets'
},
})
window.editor = editor
}
When try to wrap photoeditorsdk into a React Component as following
class Editor extends Component {
constructor (props) {
super(props)
}
componentDidMount () {
const container = this.refs.pesdk
const editor = new PhotoEditorSDK.UI.ReactUI({
container,
license: JSON.stringify(PESDK_LICENSE),
assets: {
baseUrl: '/assets'
},
title: 'Photo Editor'
})
window.editor = editor
}
render () {
return (
<div ref='pesdk'></div>
)
}
}
export default Editor
and export image using
editor.export(false).then(image => document.body.append(image))
from window.editor will encounter the errror
react-dom.development.js:5622 Uncaught TypeError: Cannot read property 'export' of null
at t.export (react-dom.development.js:5622)
at <anonymous>:1:14
I'm not able to reproduce this here. Can you give more details? E.g., where and when are you calling editor.export from. Also, are you passing an image to the editor as an option?
My forms keeps resetting if I change tabs on router-view, is there a way to prevent this (if not what's the alternative)
export class App {
configureRouter(config, router) {
config.title = "Aurelia";
config.map([
{ route: ["", "dashboard"], name: "dashboard", moduleId: "HTML/viewmodels/dashboard", nav: true, title: "Dashboard", settings: "icon-home" },
{ route: "addons", name: "addons", moduleId: "HTML/viewmodels/addons", nav: true, title: "Addons", settings: "icon-file" },
{ route: "error", name: "error", moduleId: "HTML/viewmodels/error", nav: true, title: "Error", settings: "icon-info-sign" }
]);
this.router = router;
console.log(router);
}
}
This is a state persisting issue. The easiest solution is to store state in:
The parent view
A non-view related singleton class (or static variables)
Localstorage persisting (possibly coinciding with the previous option)
The first way to do it: save it in the parent view.
For example, you could create a cache inside the App class:
export class App {
formData = {};
configureRouter(config, router) {
{ route: ["", "dashboard"], [..snip..] settings: { formData: this.formData, icon: 'icon-home' } }
}
}
Inside your view, you can then do:
activate(params, routeConfig) {
this.formData = routeConfig.settings.formData;
this.icon = routeConfig.settings.icon;
}
And in the HTML, just bind it to formData:
<input type="text" value.bind="formData.text" />
This kind of assumes, that the whole App revolves around that form. Otherwise, it wouldn't really make much sense to store it in there.
That's one way to do it, anyway (the first one I pointed out in the list).
The other way to do it: singleton.
Create a new class called AppState or something along those lines.
export class AppState {
formData = {};
}
Then in your view, you should import and inject it:
import { AppState } from './app-state';
export class YourView {
static inject = [AppState];
constructor(appState) {
this.appState = appState;
}
}
And then in your HTML, you can bind it like so:
<input type="text" value.bind="appState.formData.text" />
Or third way: a static class.
Create a new class called AppState or something along those lines.
export class AppState {
static formData = {};
}
Then in your view, you should import and inject it:
import { AppState } from './app-state';
export class YourView {
AppState = AppState;
}
And then in your HTML, you can bind it like so:
<input type="text" value.bind="AppState.formData.text" />
I'm having a weird problem with some Backbone Marionette controller in a sub-application module.
I cannot make it to work capturing one of its view events with the "controller.listenTo(view, 'event', ...)" method, although the "view.on('event',...)" works no problem.
Here is the sample code for the module views :
MyApp.module("SubApp.Selector", function (Selector, App, Backbone, Marionette, $, _) {
"use strict";
// Category Selector View
// ------------------
// Display a list of categories in the selector
// Categories list item
Selector.CategoryOption = Marionette.ItemView.extend({
template: "#my-category-template",
tagName: "option",
onRender: function () { this.$el.attr('value', this.model.get('id')); }
});
// Categories list container
Selector.CategoryListView = Marionette.CompositeView.extend({
template: "#my-category-list-template",
tagName: "div",
id: "categories",
itemView: Selector.CategoryOption,
itemViewContainer: "select",
events: {
'change #category_items': 'categoryClicked'
},
categoryClicked: function() {
var catID = this.$('#category_items').val();
console.log("category clicked "+catID);
this.trigger("category:changed", catID);
}
});
// Selector Component Controller
// -------------------------------
Selector.Viewer = Marionette.Controller.extend({
initialize: function (_options) {
this.region = _options.region;
this.collection = _options.collection;
},
show: function () {
var view = new Selector.CategoryListView({ collection: this.collection });
this.listenTo(view, 'category:changed', this.categoryChanged);
//view.on('category:changed', this.categoryChanged, this);
this.region.show(view);
},
categoryChanged: function (_category) {
console.log("category changed in controller");
}
});
});
Is there anything I got wrong about event listening from a controller object ?
Shouldn't I use the listenTo syntax as is seems to be recommended widely for proper event handling and listener destruction ?
I have two Apps:
A SrvLinkApp that has a Link Model (a sockjs connection to the server).
A ChatApp that has a chatView view, a ChatEntry Model, and a ChatCollection.
When I receive a msg form the server I trigger a 'chat:server:message', payload event with:
App.vent.trigger('chat:server:message', payload)
In my ChatApp I listen for this event, transform the payload into a ChatEntry and then add it to the ChatCollection witch is referenced by the ChatView.
Where should I add the binding? I only have the reference to the collection in the initialize part:
App.vent.bind("chat:server:msg", function(msg) {})
Plan A
Foo.module("ChatApp", function(ChatApp, App, Backbone, Marionette, $, _) {
App.addRegions({
chatRegion: "#chat-region",
});
MsgEntry = Backbone.Model.extend({});
MsgCollection = Backbone.Collection.extend({
model: MsgEntry
})
MsgView = Backbone.Marionette.ItemView.extend({
template: '#chat-entry-template',
});
MsgListView = Backbone.Marionette.CompositeView.extend({
itemView: MsgView,
itemViewContainer: "#chat-messages",
template: "#chat",
....
});
ChatApp.addInitializer(function() {
var msgCollection = new MsgCollection();
var msgListView = new MsgListView({collection: msgCollection});
// render and display the view
App.chatRegion.show(msgListView);
// App Events listeners
// --------------------
// New chat message from server
App.vent.bind("chat:server:msg", function(msg) {
// create an entry and add it to our collection
console.log(msgCollection);
});
});
});
or Plan B
Foo.module("ChatApp", function(ChatApp, App, Backbone, Marionette, $, _) {
App.addRegions({
chatRegion: "#chat-region",
});
// App Events listeners
// --------------------
// New chat message from server
App.vent.bind("chat:server:msg", function(msg) {
// create an entry and add it to our collection
console.log(ChatApp.msgCollection);
});
MsgEntry = Backbone.Model.extend({});
MsgCollection = Backbone.Collection.extend({
model: MsgEntry
})
MsgView = Backbone.Marionette.ItemView.extend({
template: '#chat-entry-template',
});
MsgListView = Backbone.Marionette.CompositeView.extend({
itemView: MsgView,
itemViewContainer: "#chat-messages",
template: "#chat",
....
});
ChatApp.addInitializer(function() {
var msgCollection = new MsgCollection();
var msgListView = new MsgListView({collection: msgCollection});
// HERE //
ChatApp.msgCollection = msgCollection;
// END HERE //
App.chatRegion.show(msgListView);
});
});
Or is there other ways to access the collection ?
I don't think either of these is bad. I use both ideas at various times. It largely depends on other circumstances within your app, what the possibilities of are of having multiple collections to deal with, etc.
Personally, I'd go with A because it keeps everything within the module, and doesn't leave the collection open to getting clobbered or forgotten about (memory leak) on the global app object.
I'm trying to pass a method from my model.js to my route.js.. And my route doesn't find any method ! I searched a solution and tested a lot of codes, without success.
I'm a beginner in Node so sorry if it's a stupid error.
This is a part of my code :
Route.js
var mongoose = require('mongoose');
var membersModel = new require('../models/MemberModel');
// Member list page
exports.list = function(req, res){
membersModel.findAll(function(err, docs){
res.render('list.jade', { title: 'My Registration App - Member list', member: docs });
});
};
MemberModel.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
// Open DB connection
var MemberSchema = new Schema({
id : ObjectId,
title : { type: String, required: true, enum: ['Mr', 'Mrs', 'Mme', 'Miss'] },
lastname : { type: String, required: true, uppercase: true, trim: true},
firstname : { type: String, required: true},
mail : { type: String, trim: true, index: { unique: true, sparse: true } },
date : Date
});
// ...
MemberSchema.method.findAll = function (callback) {
Members.find(function (err, member) {
callback(null, member)
});
};
var conn = mongoose.createConnection('mongodb://localhost/members');
var MyModel = conn.model('Members', MemberSchema);
var instanceMember = new MyModel;
module.exports = instanceMember;
Thanks for the time passed helping me.
If you want other informations, tell me !
I think you have a few problems here:
Your schema's instance methods should be defined on MemberSchema.methods (not .method).
A method like findAll that returns instances should be defined as a static method of the schema (on MemberSchema.statics) instead of an instance method.
You should be exporting MyModel, not a new MyModel instance of it as you are now. module.exports = MyModel;
route.js should not be using new in its require as you want the MyModel class to be available to the file, not an instance of it.
for the find function the syntax usually is
<modelname>.find({conditions},function(err, results){
//use the results
});
and if u don't have any specific conditions and want to find all, you can just give empty object in the conditions {}
<modelname>.find({},function(err, results){
//use the results
});
and for the schema, an example
const articleSchema = {
title: String,
content: String
};
// to create a new model named Article
const Article = mongoose.model("article",articleSchema);