- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 Backbone 和 Backbone.Marionette 很陌生。我成功地创建了一个带有某种数据网格的简单页面,该页面允许我进行分页(第一页、上一页、下一页、最后一页)、快速搜索(每次按下一个键时触发)、选择页面上显示的项目数(5 , 10, 全部, ...)
现在我有了一些工作,我试图改进它并使这些功能成为一种可重用的组件,但我不知道确切的方法。我不知道如何开始完善已经完成的工作。
例如,我希望能够在不重写所有内容的情况下更改由数据网格管理的集合/模型。这是我不自信如何做到这一点的地方,这可能是由于缺乏知识。因此,我们将非常感谢和欢迎您提出的进一步意见和建议。
// JST and HAML Assets is used for the templating pre-compilation
Backbone.Marionette.Renderer.render = function(template, data) {
if (!JST[template]) {
throw "Template '" + template + "' not found!";
}
return JST[template](data);
};
window.MyApp = new Backbone.Marionette.Application();
MyApp.addRegions({
content: ".content-box"
});
MyApp.Datagrid = (function() {
var Datagrid, ItemPerPageView, Layout, PagerView, QuickSearchView, Theme, ThemeView, Themes, ThemesView;
Datagrid = {};
Layout = Backbone.Marionette.Layout.extend({
template: "layouts/grid",
regions: {
grid: "#grid",
quickSearch: "#quickSearch",
itemPerPage: "#itemPerPage",
pager: ".pager"
}
});
Theme = Backbone.Model.extend();
Themes = Backbone.ExtendedCollection.paginatedCollection.extend({
url: "/themes",
model: Theme,
initialize: function() {
var _this = this;
MyApp.vent.on("quickSearch:term", function(term) {
_this.quickSearch(term);
});
MyApp.vent.on("itemPerPage:count", function(count) {
_this.perPage(count);
});
MyApp.vent.on("pager:previous", function() {
_this.previous();
});
MyApp.vent.on("pager:next", function() {
_this.next();
});
MyApp.vent.on("pager:first", function() {
_this.first();
});
MyApp.vent.on("pager:last", function() {
_this.last();
});
}
});
ThemeView = Backbone.Marionette.ItemView.extend({
tagName: "tr",
template: "theme",
model: Theme,
events: {
"click span": "edit",
"blur input": "save"
},
edit: function(event) {
var id, span;
id = this.model.get("id");
span = $("span", this.el).hide();
$("input", this.el).show().focus().val(span.text());
},
save: function(event) {
var id, input, span;
id = this.model.get("id");
span = $("span", this.el).show();
input = $("input", this.el).hide();
if (this.model.get("name") !== input.val()) {
this.model.set("name", input.val());
this.model.save();
}
span.text(this.model.get("name"));
}
});
ThemesView = Backbone.Marionette.CompositeView.extend({
template: "index",
model: Theme,
itemView: ThemeView,
collection: Themes,
itemViewContainer: "#themes",
serializeData: function() {
return this.data;
}
});
QuickSearchView = Backbone.Marionette.View.extend({
el: "#quickSearch",
events: {
"keyup input": "search"
},
search: function(event) {
var searchTerm;
searchTerm = this.$("input").val().trim();
MyApp.vent.trigger("quickSearch:term", searchTerm);
}
});
ItemPerPageView = Backbone.Marionette.View.extend({
el: "#itemPerPage",
events: {
"change select": "count"
},
count: function(event) {
var count;
count = this.$("select").val();
MyApp.vent.trigger("itemPerPage:count", count);
}
});
PagerView = Backbone.Marionette.View.extend({
el: ".pager",
events: {
"click #next": "next",
"click #previous": "previous",
"click #first": "first",
"click #last": "last"
},
first: function(event) {
MyApp.vent.trigger("pager:first");
},
last: function(event) {
MyApp.vent.trigger("pager:last");
},
next: function(event) {
MyApp.vent.trigger("pager:next");
},
previous: function(event) {
MyApp.vent.trigger("pager:previous");
}
});
Datagrid.initializeLayout = function() {
var collection;
Datagrid.layout = new Layout();
Datagrid.layout.on("show", function() {
MyApp.vent.trigger("layout:rendered");
});
MyApp.content.show(Datagrid.layout);
collection = new Themes();
collection.fetch();
collection.on("reset", function() {
return Datagrid.layout.grid.show(new ThemesView({
collection: collection
}));
});
};
MyApp.vent.on("layout:rendered", function() {
var itemPerPageView, pagerView, quickSearchView;
quickSearchView = new QuickSearchView();
Datagrid.layout.quickSearch.attachView(quickSearchView);
itemPerPageView = new ItemPerPageView();
Datagrid.layout.itemPerPage.attachView(itemPerPageView);
pagerView = new PagerView();
Datagrid.layout.pager.attachView(pagerView);
});
return Datagrid;
})();
MyApp.addInitializer(function() {
MyApp.Datagrid.initializeLayout();
});
$(document).ready(function() {
return MyApp.start();
});
assets
|--javascripts
|--application.js
|--admin
|--admin.js
|--admin.layout.js
|--subthemes
|--admin.subtheme.controller.js
|--admin.subtheme.view.js
|--themes
|--admin.theme.controller.js
|--admin.theme.view.js
|--templates
|--admin
|--subthemes
|--index.hamlc
|--subtheme.hamlc
|--themes
|--index.hamlc
|--theme.hamlc
|--layouts
|--grid.hamlc
//= require underscore
//= require backbone
//= require backbone.marionette
//= require_tree ./lib/backbone
//= require hamlcoffee
//= require i18n
//= require i18n/translations
//= require_tree ../templates/
//= require_tree ./admin
//= require_tree ./admin/theme
//= require_tree ./admin/subtheme
I18n.defaultLocale = "en";
Backbone.Marionette.Renderer.render = function(template, data) {
if (!JST[template]) {
throw "Template '" + template + "' not found!";
}
return JST[template](data);
};
$(document).ready(function() {
return MyApp.start();
});
var AdminRouter, TempView;
// Create the application for admin part
MyApp.Admin = new Backbone.Marionette.Application();
// Define a router to handle the grid collection type change
AdminRouter = Backbone.Marionette.AppRouter.extend({
initialize: function() {
var _this = this;
// Route quite generic to easily change the data in the grid
this.route(/^admin\/(.*?)$/, "changeCollection");
// Manage event to handle the navigation on client side
MyApp.Admin.vent.on("admin:navigate", function(link) {
_this.navigate(link, {
trigger: true
});
});
},
// Trigger an event to change the collection if one exist for the URL
changeCollection: function(collectionName) {
MyApp.Admin.vent.trigger("grid:collection:change", collectionName);
}
});
// Side menu that allows changing the collection in the data grid
SideMenuView = Backbone.Marionette.View.extend({
el: ".side-menu",
events: {
"click a": "handleClick"
},
// Prevent the normal behavior on the link click
handleClick: function(event) {
event.preventDefault();
MyApp.Admin.vent.trigger("admin:navigate", $(event.target).attr("href"));
}
});
// Add the initializer to the main application to prepare the admin part (grid)
MyApp.addInitializer(function() {
new SideMenuView();
new AdminRouter();
Backbone.history.start({
pushState: true
});
MyApp.Admin.start();
});
// This the grid layout module in the admin namespace
MyApp.Admin.module("GridLayout", function(GridLayout, Admin, Backbone, Marionette, $, _) {
var ItemPageSelectorView, Layout, PagerView, QuickSearchView;
// The quick search view handle the related fields to do the quick search
QuickSearchView = Backbone.Marionette.View.extend({
el: ".gridQuickSearch",
events: {
"keyup input": "search"
},
// Get the field content and trigger an event with it
search: function(event) {
var searchTerm;
searchTerm = $(event.target).val().trim();
$("input", this.$el).val(searchTerm);
Admin.vent.trigger("grid:quickSearch:term", searchTerm);
}
});
// The item page selecto handle the choice of how many rows should be displayed per page
ItemPageSelectorView = Backbone.Marionette.View.extend({
el: ".gridItemPageSelector",
events: {
"change select": "count"
},
// Get the number of items per page that should be displayed
count: function(event) {
var count;
count = $(event.target).val();
$("select", this.$el).val(count);
Admin.vent.trigger("grid:itemPageSelector:count", count);
}
});
// The pager view manage the view components to change the page shown in the data grid
PagerView = Backbone.Marionette.View.extend({
el: ".gridPager",
events: {
"click #next": "next",
"click #previous": "previous",
"click #first": "first",
"click #last": "last",
"click #page": "page"
},
//
// The following functions triggers events to go to the right pages
//
first: function(event) {
Admin.vent.trigger("grid:pager:first");
},
previous: function(event) {
Admin.vent.trigger("grid:pager:previous");
},
page: function(event) {
Admin.vent.trigger("grid:pager:page");
},
next: function(event) {
Admin.vent.trigger("grid:pager:next");
},
last: function(event) {
Admin.vent.trigger("grid:pager:last");
}
});
// The grid layout with the regions to display the different part of the data grid
Layout = Backbone.Marionette.Layout.extend({
template: "layouts/grid",
regions: {
gridTable: "#gridTable",
gridQuickSearch: ".gridQuickSearch",
gridItemPageSelector: ".gridItemPageSelector",
gridPager: ".gridPager"
}
});
// Once the layout is rendered, the different views are attached to the right regions
Admin.vent.on("grid:layout:rendered", function() {
var itemPageSelectorView, pagerView, quickSearchView;
quickSearchView = new QuickSearchView();
Admin.gridLayout.gridQuickSearch.attachView(quickSearchView);
itemPageSelectorView = new ItemPageSelectorView();
Admin.gridLayout.gridItemPageSelector.attachView(itemPageSelectorView);
pagerView = new PagerView();
Admin.gridLayout.gridPager.attachView(pagerView);
});
// Initializer to do at the application start
GridLayout.addInitializer(function() {
Admin.addRegions({
content: ".content-box"
});
Admin.gridLayout = new Layout();
// Trigger the rendered event when the grid layout is shown
Admin.gridLayout.on("show", function() {
Admin.vent.trigger("grid:layout:rendered");
});
// Manage the collection data change
Admin.vent.on("grid:collection:change", function(collectionName) {
// Close the previous view in the grid table region
Admin.gridLayout.gridTable.close();
// Trigger an event to fetch the collection
Admin.vent.trigger("" + collectionName + ":collection:fetch");
// Show the grid layout if not already done
if (!this.shown) {
this.shown = true;
Admin.content.show(Admin.gridLayout);
}
});
});
return GridLayout;
});
MyApp.Admin.module("ThemeController", function(ThemeController, Admin, Backbone, Marionette, $, _) {
// Define the model to use in the collection
ThemeController.Theme = Backbone.Model.extend();
// Define the collection with the related url on the server. The collection extends a paginated collection that has the methods to manage the quick search and the pagination
ThemeController.Themes = Backbone.ExtendedCollection.paginatedCollection.extend({
url: "/admin/themes",
model: ThemeController.Theme,
initialize: function() {
var _this = this;
//
// The following functions handle the events for the quick search and pagination
//
Admin.vent.on("grid:quickSearch:term", function(term) {
_this.quickSearch(term);
});
Admin.vent.on("grid:itemPageSelector:count", function(count) {
_this.perPage(count);
});
Admin.vent.on("grid:pager:previous", function() {
_this.previous();
});
Admin.vent.on("grid:pager:next", function() {
_this.next();
});
Admin.vent.on("grid:pager:first", function() {
_this.first();
});
return MyApp.Admin.vent.on("grid:collection:fetched", function() {
Admin.gridLayout.gridTable.show(new Admin.ThemeView.Table({
collection: _this
}));
});
}
});
// At the application initilization, we need to be sure this controller can
// handle the event to fetch the data from the server
Admin.addInitializer(function() {
Admin.vent.on("themes:collection:fetch", function() {
ThemeController.themes = new ThemeController.Themes();
// Once the data are fetched from the server, trigger an event to display them
ThemeController.themes.fetch({
success: function() {
Admin.vent.trigger("grid:collection:fetched");
}
});
});
});
});
MyApp.Admin.module("ThemeView", function(ThemeView, Admin, Backbone, Marionette, $, _) {
// The view to show one item in a row of the data grid
ThemeView.Item = Backbone.Marionette.ItemView.extend({
tagName: "tr",
template: "admin/themes/theme",
model: Admin.ThemeController.Theme
});
// The view to show the collection of item
ThemeView.Table = Backbone.Marionette.CompositeView.extend({
template: "admin/themes/index",
model: Admin.ThemeController.Theme,
itemView: ThemeView.Item,
collection: Admin.ThemeController.Themes,
itemViewContainer: "#themes",
// ! I was force to add this to have data in the original format that is used by my templates !
serializeData: function() {
return this.data;
}
});
});
.gridPager
%button#first= "<<"
%button#previous= "<"
%button#next= ">"
%button#last= ">>"
%span.gridItemPageSelector= "Item per page"
%select
%option= 5
%option= 10
%option{"value" => -1}= "All"
%span.gridQuickSearch= "Quick search:"
%input#gridSearchTerm{"type" => "text"}
#gridTable
%span.gridItemPageSelector= "Item per page"
%select
%option= 5
%option= 10
%option{"value" => -1}= "All"
%span.gridQuickSearch= "Quick search:"
%input#gridSearchTerm{"type" => "text"}
.gridPager
%button#first= "<<"
%button#previous= "<"
%button#next= ">"
%button#last= ">>"
%table.table.table-striped
%thead
%tr
%th= "Id"
%th= "Name"
%tbody#themes
%td= this.id
%td= this.name
最佳答案
好吧,我不是一个大专家,但这就是我使用 Marionette 和 Requirejs 做到的:
a) 我创建了一个通用的 Grid Layout wiew,它由我的 approuter 使用一些参数调用,如集合、cols 配置(我用每个循环渲染表头)和行 View :
showUsers: function(){
require(['views/GridGen','collections/user_collection'], function(Grid, UserCollection){
var Users = new UserCollection();
App.grid = new Grid({collection: Users ,
rowView: 'rowUser',
cols_config: App.tables.users});
App.page.show(App.grid);
});
},
var Grid = Backbone.Marionette.Layout.extend({
regions: {
top_controls: "#top_controls",
table_view: "#table_view",
pagination_controls: "#pagination_controls",
bottom_controls: "#bottom_controls",
},
onShow: function(){
this.renderTable(this.collection);
},
renderTable: function(collection){
collection.fetch({success:function(){
require(['views/'+self.options.rowView+'.js'],function(iView){
var vista = new View({collection: collection, itemView: iView, thead: self.options.cols_config});
App.grid.table_view.show(vista);
self.renderPagination(collection);
collection.pager();
});
}});
}
var View = Backbone.Marionette.CompositeView.extend({
initialize: function(){
this.itemView = this.options.itemView;
},
serializeData: function(){
var data = Backbone.Marionette.ItemView.prototype.serializeData.apply(this, arguments);
data.thead = this.options.thead;
return data;
},
appendHtml: function(collectionView, itemView, index){
collectionView.$("tbody").append(itemView.el);
},
关于backbone.js - 如何创建可重用的主干/backbone.marionette 组件,例如数据网格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12085693/
我错过了什么,我已完成 的安装指南中要求的所有步骤 native 脚本 运行 tns doctor 给我以下输出... C:\abc\xyz>tns doctor √ Getting environm
尝试从 {addToCart(book)}}/>}> 传递数据至}> 问题: 购物车 ( render={()=> ) 收到 null,但没有收到我尝试发送的对象 已放置“console.log...
这是 _app.tsx 的外观: function MyApp({ Component, pageProps }: AppProps) { return } 我在构建项目时遇到了这个错误: Ty
我的 Laravel Vue 组件收到以下警告: [Vue warn]: Avoid mutating a prop directly since the value will be overwrit
根据这个example更详细this one我刚刚遇到了一件奇怪的事情...... 如果我使用方法作为 addTab(title,icon,component) 并且下一步想使用 setTabComp
目前我有一个捕获登录数据的表单,一个带有 TIWDBGrid 的表单,它应该返回与我从我的 mysql 数据库登录时创建的 user_id 关联的任何主机,以及一个共享数据模块。 下面是我的登录页面代
在我的react-native应用程序中,我目前有一个本地Android View (用java编写)正确渲染。当我尝试将我的react-native javascript 组件之一放入其中时,出现以
我为作业编写了简单的代码。我引用了文档和几个 youtube 视频教程系列。我的 react 代码是正确的我在运行代码时没有收到任何错误。但是这些 react-boostrap 元素没有渲染。此代码仅
几周前我刚刚开始使用 Flow,从一周前开始我就遇到了 Flow 错误,我不知道如何修复。 代码如下: // @flow import React, { Component } from "react
我想在同一个 View 中加载不同的 web2py 组件,但不是同时加载。我有 5 个 .load 文件,它们具有用于不同场景的表单字段,这些文件由 onchange 选择脚本动态调用。 web2py
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
Blazor 有 InputNumber将输入限制为数字的组件。然而,这呈现了一个 firefox 不尊重(它允许任何文本)。 所以我尝试创建一个过滤输入的自定义组件: @inherits Inpu
我在学习 AngularDART 组件时编写了以下简单代码,但没有显示任何内容,任何人都可以帮助我知道我犯了什么错误: 我的 html 主文件:
我想在初始安装组件时或之后为 div 设置动画(淡入)。动画完成后,div 不应消失。我正在尝试使用 CSSTransition 组件并查看 reactcommunity.org 上的示例,但我根本无
我需要一个 JSF 组件来表示甘特图。是否有任何组件库(如 RichFaces)包含这样的组件? 最佳答案 JFreeChart有甘特图和PrimeFaces有一个图像组件,允许您动态地流式传输内容。
从软件工程的角度来看,组件、模块和子系统之间有什么区别? 提前致谢! 最佳答案 以下是 UML 2.5 的一些发现: 组件:该子句指定一组结构,可用于定义任意大小和复杂性的软件系统。特别是,它将组件指
我有使用非托管程序集(名为 unmanaged.dll)的托管应用程序(名为 managed.exe)。到目前为止,我们已经创建了 Interop.unmanaged.dll,managed.exe
我有一个跨多个应用程序复制的 DAL(我知道它的设计很糟糕,但现在忽略它),我想做的是这个...... 创建一个将通过所有桌面应用程序访问的 WCF DAL 组件。任何人都可以分享他们对关注的想法吗?
我有一个 ComboBox 的集合声明如下。 val cmbAll = for (i /** action here **/ } 所有这些都放在一个 TabbedPane 中。我想这不是问题。那么我
使用 VB6 创建一个 VB 应用程序。应用程序的一部分显示内部的闪存。 当我使用 printform它只是打印整个应用程序。我不知道如何单独打印闪光部分。任何帮助,将不胜感激!.. 谢谢。 最佳答案
我是一名优秀的程序员,十分优秀!