I am trying to create a custom data adapter according to an example here: http://select2.github.io/announcements-4.0.html#query-to-data-adapter.
How can I move the line that creates the select2 control outside the function with definition of DataAdapter (see the code below)?
<!DOCTYPE html>
<head>
<title></title>
<link href="select2.css" rel="stylesheet" />
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.js"></script>
<script type="text/javascript" src="select2.full.js"></script>
<script type="text/javascript">
$.fn.select2.amd.require(
['select2/data/array', 'select2/utils'],
function (ArrayData, Utils) {
function CustomData ($element, options) {
CustomData.__super__.constructor.call(this, $element, options);
}
Utils.Extend(CustomData, ArrayData);
CustomData.prototype.query = function (params, callback) {
var data = {results: []};
data.results.push({id: params.term, text: params.term});
data.results.push({id: 11, text: 'aa'});
data.results.push({id: 22, text: 'bb'});
callback(data);
};
// Works if uncommented, but this line needs to be elsewhere (in $(document).ready()).
//$("#my").select2({tags: true, dataAdapter: CustomData});
});
$(document).ready(function() {
// This line does not work here.
$("#my").select2({tags: true, dataAdapter: CustomData});
});
</script>
</head>
<body>
<select id="my"></select>
</body>
</html>
you define it via AMD-Pattern:
$.fn.select2.amd.define('select2/data/customAdapter',[
'select2/data/array',
'select2/utils'
],
function (ArrayAdapter, Utils) {
function CustomDataAdapter ($element, options) {
CustomDataAdapter.__super__.constructor.call(this, $element, options);
}
Utils.Extend(CustomDataAdapter, ArrayAdapter);
CustomDataAdapter.prototype.current = function (callback) {
callback(...);
};
return CustomDataAdapter;
}
);
var customAdapter=$.fn.select2.amd.require('select2/data/customAdapter');
$("#my").select2({
tags: true,
dataAdapter: customAdapter
});
For anyone trying to extend select2, here is an example :
// Require the adapter you want to override
$.fn.select2.amd.require(["select2/data/select"], function (Select) {
let CustomDataAdapter = Select;
// Simple example, just override the function
CustomDataAdapter.prototype.current = function (callback) {
// Your own code
};
// Example modifying data then calling the original function (which we need to keep)
let originalSelect = CustomDataAdapter.prototype.select;
CustomDataAdapter.prototype.select = function (data) {
// Your own code
// Call the original function while keeping 'this' context
originalSelect.bind(this)(data);
};
// Finally, use the custom data adapter
$('#my-select').select2({
dataAdapter: CustomDataAdapter
});
});
Example of select2 to handle big array. I am fetching data from server using ajax. Handling searching and pagination locally with more than 20000 data json.
<select id="widget_project"></select>
<script>
$(function () {
allProjects;// having all project json data
pageSize = 50
jQuery.fn.select2.amd.require(["select2/data/array", "select2/utils"],
function (ArrayData, Utils) {
function CustomData($element, options) {
CustomData.__super__.constructor.call(this, $element, options);
}
Utils.Extend(CustomData, ArrayData);
CustomData.prototype.query = function (params, callback) {
var results = [];
if(p_term !== "" && typeof params.term === "undefined"){
params.term = p_term;
console.log(params.term);
}
if (params.term && params.term !== '') {
p_term = params.term;
results = findItem(params.term);
} else {
results = allProjects;
}
if (!("page" in params)) {
params.page = 1;
}
var data = {};
data.results = results.slice((params.page - 1) * pageSize, params.page * pageSize);
data.pagination = {};
data.pagination.more = params.page * pageSize < results.length;
callback(data);
};
$(document).ready(function () {
$("#widget_project").select2({
minimumInputLength: 3,
placeholder:"Select a project",
ajax: {},
dataAdapter: CustomData
});
});
})
});
</script>
Related
Inside my layout page i wanna run a script for translate the text of some enumumerators.
My layout looks like this:
<html>
<head>
...
<script src="~/js/ViewModels/Helpers/Translation.js"></script>
<script src="~/js/ViewModels/Helpers/Enumerators.js"></script>
...
</head>
<body>
...
</body>
</html>
My translation script:
'use strict';
var jsonTranstation = null;
$(function () {
getjson();
});
const getjson = () => {
$.getJSON('/lib/translation/en-EN.json', function (data) {
jsonTranstation = data;
});
}
const Translation = (value, ViewModel) => {
let a = null;
if (jsonTranstation ) {
a = jsonTranstation[ViewModel][value];
return a;
}
return '--';
}
My Enumerators script:
'use strict'
const EnumToolBar = {
NEW: { text: Translation('New', 'EnumToolBar'), prefixIcon: 'e-add', id: 'NEW' }
}
My JSON file (en-EN.json):
{
"EnumToolBar": {
"New": "New Value"
}
}
Using EnumToolBar.NEW.text in HomePage returns '--' instead of 'New Value'.
There are any way to read first script and the respective json file before any other script?
I made this JS to add a functionality on a form (backend) that computes a field when the event click is triggered. So far the code recomputes when I use ".include" but the whole JS in all views fail since I'm using ".include". When I try to use extend my code does nothing. Looks like Odoo doesn't add the extended code to the JS engine so my question is, what am I doing wrong here? Is there something else I need to add so my code works as extended?
odoo.define('med_care.TestRenderer', function (require) {
"use strict";
var viewRegistry = require('web.view_registry');
var FormRenderer = require('web.FormRenderer');
var FormView = require('web.FormView');
var TestFormRenderer = FormRenderer.extend({
events: _.extend({}, FormRenderer.prototype.events, {
'click .sign_selector': '_onSignSelectorClicked',
}),
init: function (parent, state, params) {
this._super.apply(this, arguments);
this.fields = state.fields;
this._onSignSelectorClicked = _.debounce(this._onSignSelectorClicked, 300, true);
},
confirmChange: function (state, id, fields, e) {
var self = this;
if (state.model == 'med.test') {
return this._super.apply(this, arguments).then(function () {
self.canBeSaved(self.state.id);
});
}
},
_onSignSelectorClicked: function (event) {
this.state.data.telephone = '333';
if (this.state.model == 'med.test') {
var info_test = {
dataPointID: this.state.id,
changes: {telephone: '333'},
viewType: "form",
notifyChange: true
};
var odoo_event = this.trigger_up('field_changed', info_test);
this.confirmChange(this.state, this.state.id, "telephone",
odoo_event)
}
},
});
var TestFormView = FormView.extend({
config: _.extend({}, FormView.prototype.config, {
Renderer: TestFormRenderer,
}),
});
viewRegistry.add('test_form', TestFormView);
return TestFormView;
});
In Polymer 0.5 the advice on globals was as outlined in this question/answer:
Polymer global variables
However in Polymer 1.0 this doesn't seem to work. Change notifications are not automatically generated on the underlying model, they are generated on the <dom-module> instead which means that change notifications will be generated on only one of the <app-globals>.
What is the recommended way of implementing this pattern in Polymer 1.0?
Polymer element <iron-meta> is also an option. For me this was the easiest solution.
I've extended Etherealones' solution to work as a Behavior, and to extend Polymers "set" and "notifyPath" methods to trigger the updates automatically. This is as close as i could get to a true databinding across components/elements:
globals-behavior.html:
<script>
var instances = [];
var dataGlobal = {};
var GlobalsBehaviour = {
properties: {
globals: {
type: Object,
notify: true,
value: dataGlobal
}
},
ready: function() {
var _setOrig = this.set;
var _notifyPathOrig = this.notifyPath;
this.set = function() {
_setOrig.apply(this, arguments);
if (arguments[0].split(".")[0] === "globals") {
this.invokeInstances(_notifyPathOrig, arguments);
}
};
this.notifyPath = function(path, value) {
_notifyPathOrig.apply(this, arguments);
if (arguments[0].split(".")[0] === "globals") {
this.invokeInstances(_notifyPathOrig, arguments);
}
};
},
invokeInstances: function(fn, args) {
var i;
for (i = 0; i < instances.length; i++) {
instance = instances[i];
if (instance !== this) {
fn.apply(instance, args);
}
}
},
attached: function() {
instances.push(this);
},
detached: function() {
var i;
i = instances.indexOf(this);
if (i >= 0) {
instances.splice(i, 1);
}
}
};
</script>
And in all polymer elements that should have access to the globals variable:
<script>
Polymer({
is: 'globals-enabled-element',
behaviors: [GlobalsBehaviour]
});
</script>
Examples:
I have posted a full example as a Gist on Github
Here's a snippet to see it in action:
<!DOCTYPE html>
<html>
<head>
<title>Globals Behavior Example</title>
<link rel="import" href="//rawgit.com/Polymer/polymer/master/polymer.html">
<dom-module id="globals-enabled-element">
<template>
<input type="text" value="{{globals.my_variable::input}}">
</template>
<script>
var instances = [];
var dataGlobal = {};
var GlobalsBehaviour = {
properties: {
globals: {
type: Object,
notify: true,
value: dataGlobal
}
},
ready: function() {
var _setOrig = this.set;
var _notifyPathOrig = this.notifyPath;
this.set = function() {
_setOrig.apply(this, arguments);
if (arguments[0].split(".")[0] === "globals") {
this.invokeInstances(_notifyPathOrig, arguments);
}
};
this.notifyPath = function(path, value) {
_notifyPathOrig.apply(this, arguments);
if (arguments[0].split(".")[0] === "globals") {
this.invokeInstances(_notifyPathOrig, arguments);
}
};
},
invokeInstances: function(fn, args) {
var i;
for (i = 0; i < instances.length; i++) {
instance = instances[i];
if (instance !== this) {
fn.apply(instance, args);
}
}
},
attached: function() {
instances.push(this);
},
detached: function() {
var i;
i = instances.indexOf(this);
if (i >= 0) {
instances.splice(i, 1);
}
}
};
</script>
<script>
Polymer({
is: 'globals-enabled-element',
behaviors: [GlobalsBehaviour]
});
</script>
</dom-module>
</head>
<body>
<template is="dom-bind">
<p>This is our first polymer element:</p>
<globals-enabled-element id="element1"></globals-enabled-element>
<p>And this is another one:</p>
<globals-enabled-element id="element2"></globals-enabled-element>
</template>
</body>
</html>
I have implemented a pattern like iron-signals uses for this purpose. So the basic principle is that you manually notify other instances when an update occurs.
Consider this:
<dom-module id="x-global">
<script>
(function() {
var instances = [];
var dataGlobal = {};
Polymer({
is: 'x-global',
properties: {
data: {
type: Object,
value: dataGlobal,
},
},
attached: function() {
instances.push(this);
},
detached: function() {
var i = instances.indexOf(this);
if (i >= 0) {
instances.splice(i, 1);
}
},
set_: function(path, value) {
this.set(path, value);
instances.forEach(function(instance) {
if (instance !== this) { // if it is not this one
instance.notifyPath(path, value);
}
}.bind(this));
},
notifyPath_: function(path, value) {
instances.forEach(function(instance) {
instance.notifyPath(path, value);
});
},
fire_: function(name, d) {
instances.forEach(function(instance) {
instance.fire(name, d);
});
},
});
})();
</script>
</dom-module>
You will simple call the version that have an underscore suffix like fire_ when you are firing an event. You can even create a Polymer Behavior of some sort with this pattern I guess.
Beware that preceding underscore properties are already used by Polymer so don't go ahead and convert these to _fire.
P.S.:
I didn't look around to solve how to reflect the notification of this.push(array, value); as I don't need it. I don't know if it's possible this way. Should go find Polymer.Base.push.
Sjmiles, one of Polymer's creators just posted the following snippet to the Polymer slack room as an example of shared data:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="shared-data element and repeats">
<base href="http://milestech.net/components/">
<script href="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
</head>
<body>
<demo-test></demo-test>
<script>
(function() {
var private_data = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
Polymer({
is: 'private-shared-data',
properties: {
data: {
type: Object,
notify: true,
value: function() {
return private_data;
}
}
}
});
})();
Polymer({
is: 'xh-api-device',
properties: {
data: {
type: Array,
notify: true
},
_share: {
value: document.createElement('private-shared-data')
}
},
observers: [
'dataChanged(data.*)'
],
ready: function() {
this.data = this._share.data;
this.listen(this._share, 'data-changed', 'sharedDataChanged');
},
dataChanged: function(info) {
this._share.fire('data-changed', info, {bubbles: false});
},
sharedDataChanged: function(e) {
this.fire(e.type, e.detail);
},
add: function(name) {
this.push('data', {name: name});
}
});
</script>
<dom-module id="demo-test">
<template>
<h2>One</h2>
<xh-api-device id="devices" data="{{data}}"></xh-api-device>
<template is="dom-repeat" items="{{data}}">
<div>name: <span>{{item.name}}</span></div>
</template>
<h2>Two</h2>
<xh-api-device data="{{data2}}"></xh-api-device>
<template is="dom-repeat" items="{{data2}}">
<div>name: <span>{{item.name}}</span></div>
</template>
<br>
<br>
<button on-click="populate">Populate</button>
</template>
<script>
Polymer({
populate: function() {
this.$.devices.add((Math.random()*100).toFixed(2));
// this works too
//this.push('data', {name: (Math.random()*100).toFixed(2)});
}
});
</script>
</dom-module>
</body>
</html>
I've actually moved my app to using simple data binding, so I'm not sure of the validity of this approach, but maybe it would be useful to someone.
I have tried to improve on Alexei Volkov's answer, but I wanted to define the global variables separately. Instead of the getters/setters I used the observer property and saved the key together with the instances.
The usage is:
<app-data key="fName" data="{{firstName}}" ></app-data>
whereas the keyproperty defines the name of the global variable.
So for example you can use:
<!-- Output element -->
<dom-module id="output-element" >
<template>
<app-data key="fName" data="{{data1}}" ></app-data>
<app-data key="lName" data="{{data2}}" ></app-data>
<h4>Output-Element</h4>
<div>First Name: <span>{{data1}}</span></div>
<div>Last Name: <span>{{data2}}</span></div>
</template>
</dom-module>
<script>Polymer({is:'output-element'});</script>
Definition of the <app-data>dom module:
<dom-module id="app-data"></dom-module>
<script>
(function () {
var instances = [];
var vars = Object.create(Polymer.Base);
Polymer({
is: 'app-data',
properties: {
data: {
type: Object,
value: '',
notify: true,
readonly: false,
observer: '_data_changed'
},
key: String
},
created: function () {
key = this.getAttribute('key');
if (!key){
console.log(this);
throw('app-data element requires key');
}
instances.push({key:key, instance:this});
},
detached: function () {
key = this.getAttribute('key');
var i = instances.indexOf({key:key, instance:this});
if (i >= 0) {
instances.splice(i, 1);
}
},
_data_changed: function (newvalue, oldvalue) {
key = this.getAttribute('key');
if (!key){
throw('_data_changed: app-data element requires key');
}
vars.set(key, newvalue);
// notify the instances with the correct key
for (var i = 0; i < instances.length; i++)
{
if(instances[i].key == key)
{
instances[i].instance.notifyPath('data', newvalue);
}
}
}
});
})();
</script>
Fully working demo is here: http://jsbin.com/femaceyusa/1/edit?html,output
I've combined all suggestions above into the following global polymer object
<dom-module id="app-data">
</dom-module>
<script>
(function () {
var instances = [];
var vars = Object.create(Polymer.Base);
var commondata = {
get loader() {
return vars.get("loader");
},
set loader(v) {
return setGlob("loader", v);
}
};
function setGlob(path, v) {
if (vars.get(path) != v) {
vars.set(path, v);
for (var i = 0; i < instances.length; i++) {
instances[i].notifyPath("data." + path, v);
}
}
return v;
}
Polymer({
is: 'app-data',
properties: {
data: {
type: Object,
value: commondata,
notify: true,
readonly: true
}
},
created: function () {
instances.push(this);
},
detached: function () {
var i = instances.indexOf(this);
if (i >= 0) {
instances.splice(i, 1);
}
}
});
})();
</script>
and use it elsewere like
<dom-module id="app-navigation">
<style>
</style>
<template>
<app-data id="data01" data="{{data1}}" ></app-data>
<app-data id="data02" data="{{data2}}"></app-data>
<span>{{data1.loader}}</span>
<span>{{data2.loader}}</span>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'app-navigation',
properties: {
},
ready: function () {
this.data1.loader=51;
}
});
})();
</script>
Changing either data1.loader or data2.loader affects other instances. You should to extend commondata object to add more global properties like it shown with loader property.
It is much easier to achieve the same effect of global variables if you wrapped your application in a template. Watch the explanation in this video (I linked to the exact minute and second where the concept is explained).
Using ootwch's solution, I ran into a race condition situation with lazy-loaded components.
As posted, lazy-loaded components are not initialized with the value from the shared data.
In case anyone else runs into the same problem, I think I fixed it by adding a ready callback like this:
ready: function() {
const key = this.getAttribute('key')
if (!key) {
throw new Error('cm-app-global element requires key')
}
const val = vars.get(key)
if (!!val) {
this.set('data', val)
}
},
Hope this saves someone some pain.
I have tried to reload the data populated by an ajax call but I cant get it to work, it shows the old data even after using the reload method. The thing is that if I change some variables to populate a different data and try to call the following code without refreshing the page it does not reload the updated data =/ Here is my code:
function populateDataGrid() {
$.ajaxSetup({async: false});
var gridinfo="";
$.post("lib/function.php",{activity: activity, shift: shift, date: date},
function (output){
gridinfo = JSON.parse(output);
});
$.ajaxSetup({async: true});
// INITIALIZING THE DATAGRID
var dataSource = new StaticDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) {
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
data: gridinfo,
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-fast-appointment-results').modal({show:true});
}
I found a solution... I had to create a new DataSource (lets call it "AjaxDataSource") and add the ajax request functionality within the data constructor:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['underscore'], factory);
} else {
root.AjaxDataSource = factory();
}
}(this, function () {
var AjaxDataSource = function (options) {
this._formatter = options.formatter;
this._columns = options.columns;
this._delay = options.delay || 0;
this._data = options.data;
};
AjaxDataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
setTimeout(function () {
var data;
$.ajax({
url: 'getdata.php',
type: 'POST',
data: 'param1:param1,param2,param2,...,paramN:paramN', // this is optional in case you have to send some params to getdata.php
dataType: 'json',
async: false,
success: function(result) {
data = result;
},
error: function(data){
//in case we want to debug and catch any possible error
// console.log(data);
}
});
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
var match = false;
_.each(item, function (prop) {
if (_.isString(prop) || _.isFinite(prop)) {
if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
}
});
return match;
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
}, this._delay)
}
};
return AjaxDataSource;
}));
After defining the new DataSource, we just need to create it and call the datagrid as usual:
function populateDataGrid(){
// INITIALIZING THE DATAGRID
var dataSource = new AjaxDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) { // in case we want to add customized items, for example a button
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-results').modal({show:true});
}
So now we have our datagrid with data populated via ajax request with the ability to reload the data without refreshing the page.
Hope it helps someone!
I am new to backbone.js and is having some problem with my app. I have a collection which relies on a json data source. I am able to console.log the json in my parse method. Is that enough to bind the collection to my view? I don't understand the use of fetch method.
My collection looks like as follows,
(function (collections,model) {
collections.Directory = Backbone.Collection.extend({
initialize : function(){
console.log('we are here');
},
model:model.item,
url:'collections/json/data.json',
parse:function(response){
console.log(response);
return response;
}
});
})(app.collections,app.models);
And my master view looks like this,
(function(views,collections){
views.masterView = Backbone.View.extend({
el : $("#contacts"),
initialize : function(){
console.log('view initialize inside render');
this.render();
this.$el.find("#filter").append(this.createSelect());
this.on("change:filterType", this.filterByType, this);
this.collection.on("reset", this.render, this);
this.collection.on("add", this.renderContact, this);
//console.log('we are here'+app.collections.CollectionItems.fetch());
console.log('view initialize');
},
render : function(){
this.$el.find("article").remove();
_.each(this.collection.models,function(item){
this.renderContact(item);
},this);
},
renderContact: function (item) {
views.contactView = new app.views.ContactView({
model: item
});
this.$el.append(contactView.render().el);
},
getTypes : function () {
return _.uniq(this.collection.pluck("Qno"));
},
createSelect : function () {
var select = $("<select/>", {
html: "<option value='all'>All</option>"
});
_.each(this.getTypes(), function (item) {
var option = $("<option/>", {
value: item.toLowerCase(),
text: item.toLowerCase()
}).appendTo(select);
});
return select;
},
events: {
"change #filter select": "setFilter",
"click #add": "addContact",
"click #showForm": "showForm"
},
setFilter : function(e){
this.filterType = e.currentTarget.value;
this.trigger("change:filterType");
},
filterByType: function () {
if (this.filterType === "all") {
this.collection.reset(contacts);
routerURL.navigate("filter/all");
} else {
this.collection.reset(contacts, { silent: true });
var filterType = this.filterType,
filtered = _.filter(this.collection.models, function (item) {
return item.get("type").toLowerCase() === filterType;
});
this.collection.reset(filtered);
routerURL.navigate("filter/"+filterType);
}
},
addContact : function(e){
e.preventDefault();
var contModel = {};
$("#addContact").children("input").each(function(i, el){
if($(el).val() !== "")
contModel[el.id] = $(el).val();
});
contacts.push(contModel);
if (_.indexOf(this.getTypes(), contModel.type) === -1) {
this.collection.add(new Contact(contModel));
this.$el.find("#filter").find("select").remove().end().append(this.createSelect());
} else {
this.collection.add(new Contact(contModel));
}
},
showForm : function(){
this.$el.find("#addContact").slideToggle();
}
});
})(app.views,app.collections);
my model is very simple and looks like this,
(function ( models ) {
models.Item = Backbone.Model.extend({
defaults :{Qno:'1',Desc:'hello'}
});
})( app.models );
ihave one js file instantiatin viewsand collections
(function () {
window.app = {};
app.collections = {};
app.models = {};
app.views = {};
app.mixins = {};
$(function(){
app.collections.CollectionItems = new app.collections.Directory();
//app.collections.CollectionItems.fetch();
//console.log(app.collections.CollectionItems.fetch());
app.collections.CollectionItems.fetch({
success: function (collection,response) {
console.log(response);
}
});
//console.log(app.collections.CollectionItems.toJSON());
console.log('coll started');
app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
console.log('view is jus about fine!!');
//app.views.pagination = new app.views.PaginatedView({collection:app.collections.paginatedItems});
});
var ContactsRouter = Backbone.Router.extend({
routes: {
"filter/:type": "urlFilter"
},
urlFilter: function (type) {
master.filterType = type;
master.trigger("change:filterType");
}
});
var routerURL = new ContactsRouter();
Backbone.history.start();
})();
my landing page looks like this with a template in it
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Backbone.js Web App</title>
<link rel="stylesheet" href="css/screen.css" />
</head>
<body>
<div id="contacts">
</div>
<script id="contactTemplate" type="text/template">
<h1><%= Qno %></h1>
</script>
<script src="js/jquery.js"></script>
<script src="js/underscore-min.js"></script>
<script src="js/backbone-min.js"></script>
<script src="app.js"></script>
<script src="collections/Directory.js"></script>
<script src="models/item.js"></script>
<script src="views/masterView.js"></script>
<script src="views/simpleView.js"></script>
<!--<script src="js/backbone.paginator.js"></script>-->
</body>
</html>
I just can't get my head around this. The view is not rendered with the collection data. Please help!
I think it's because the fetch method on your collection is executed asynchronously and has therefore not completed when you create your view (if you look at the console I would expect the log statement in the success callback to display after the log statements underneath). This means that your view render method is called before the collection is populated and the reset event (which you're binding to in your view) is never triggered.
Try updating the code which instantiates everything as follows:
$(function(){
app.collections.CollectionItems = new app.collections.Directory();
//app.collections.CollectionItems.fetch();
//console.log(app.collections.CollectionItems.fetch());
app.collections.CollectionItems.fetch({
success: function (collection,response) {
console.log(response);
app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
}
});
});