BackBone Views Events Hash - javascript

I am new to backbone and am doing a project to teach myself. For some reason I cannot get the events hash to work so I did a good amount of things in the initialize function instead. How would I use the events hash in my view below?
var PictureView = Backbone.View.extend({
el: "#app",
initialize: function() {
$('.button').click(function() {
this.request();
}.bind(this))
},
request: function(text) {
var text = $('#text').val();
this.getPicture(text, function(url) {
console.log(arguments)
//append it to the image tag;
$("#random").attr("src", url)
});
},
getPicture: function(tags, cb) {
$.getJSON(
"https://api.flickr.com/services/rest/?jsoncallback=?", {
method: 'flickr.photos.search',
tags: tags,
api_key: apiKey,
format: 'json',
nojsoncallback: 1,
per_page: 10 // you can increase this to get a bigger array
},
function(data) {
if (data.stat === 'ok') {
var photo = data.photos.photo[Math.floor(Math.random() * data.photos.photo.length)];
$.getJSON(
"https://api.flickr.com/services/rest/?jsoncallback=?", {
method: 'flickr.photos.getSizes',
api_key: apiKey,
photo_id: photo.id,
format: 'json',
nojsoncallback: 1
},
function(response) {
console.log(response);
if (response.stat === 'ok') {
var the_url = response.sizes.size[5].source;
cb(the_url);
} else {
console.log(" The request to get the picture was not good :\ ")
}
}
);
} else {
alert("no pictures found for that tag :'(");
}
}
);
}
})

Your button is outside the div with id #app. In Backbone, for the events hash to work, the elements you want to use the events on, should be inside your el.
<center><div id="app">
<center><button class="button">Click Me to add an image</button</center>
</div></center>
Now you can use the events hash as
el: "#app",
events: { 'click .button': 'request' },
initialize : function(){}

Related

Changing Vue.js example to use ajax

Im using Vue.js in my latest project and in part of the project i need to render a tree view which is stored in a db - Im using the Vue.js tree view example as a base and have the data coming from my server in the correct format.
Ive found a way to modify the example to load the data from js but by the time it does, the component has already been rendered. Ive checked that the data works when I preload a var with the data from the server.
How would I change things to make this load from ajax?
My js:
Vue.component('item', {
template: '#item-template',
props: {
model: Object
},
data: function() {
return {
open: false
}
},
computed: {
isFolder: function() {
return this.model.children && this.model.children.length
}
},
methods: {
toggle: function() {
if (this.isFolder) {
this.open = !this.open
}
},
changeType: function() {
if (!this.isFolder) {
Vue.set(this.model, 'children', [])
this.addChild()
this.open = true
}
}
}
})
var demo = new Vue({
el: '#demo',
data: {
treeData: {}
},
ready: function() {
this.fetchData();
},
methods: {
fetchData: function() {
$.ajax({
url: 'http://example.com/api/categories/channel/treejson',
type: 'get',
dataType: 'json',
async: false,
success: function(data) {
var self = this;
self.treeData = data;
}
});
}
}
})
the template :
<script type="text/x-template" id="item-template">
<li>
<div
:class="{bold: isFolder}"
#click="toggle"
#dblclick="changeType">
#{{model.name}}
<span v-if="isFolder">[#{{open ? '-' : '+'}}]</span>
</div>
<ul v-show="open" v-if="isFolder">
<item
class="item"
v-for="model in model.children"
:model="model">
</item>
</ul>
</li>
</script>
And the html:
<ul id="demo">
<item
class="item"
:model="treeData">
</item>
</ul>
The problem is in the $.ajax() call. The value of self in the success handler has the wrong value
success: function(data) {
var self = this; // this = jqXHR object
self.treeData = data;
}
Either use the context option and this.treeData
$.ajax({
url: 'http://example.com/api/categories/channel/treejson',
type: 'get',
context: this, // tells jQuery to use the current context as the context of the success handler
dataType: 'json',
async: false,
success: function (data) {
this.treeData = data;
}
});
Or move the var self = this line in the correct place right before $.ajax();
fetchData: function () {
var self = this;
$.ajax({
url: 'http://example.com/api/categories/channel/treejson',
type: 'get',
dataType: 'json',
async: false,
success: function (data) {
self.treeData = data;
}
});
}

JStree Async Search

Whe are busy building a web based app. And we inherited the code where the previous developers used jstree so now the whole site consist out of a tree that uses jstree.
Everything worked even the search on the tree, but then we came across a problem where certain tabs loaded too long because of the tree which was too big.
So we went and made the the tree async / lazy loading which works perfectly but know the problem is that the search doesn't work that well.
Because we made a api for the search which works but it doesn't do the call back after new tree has been loaded.
Can someone help because I've been struggling for 3 days now and its giving me a head ache.
// Tree Search
searchAjaxFunction: function () {
var TreeCustomApiRequest = {
nTreeCustomDesc: document.getElementById("tree_search").value,
nUserId: document.getElementById("TrendUserID").value,
nAccessLevel: document.getElementById("hfTrendAccessLevel").value
}
$.ajax({
type: "POST",
data: JSON.stringify(TreeCustomApiRequest),
url: 'api/TreeCustomSearch.aspx',
success: function (jsonData)
{
Tree.dataJson = jsonData;
// Clear the tree.
//Tree.dataJson = jsonData;
if ($("#tree").jstree()) {
$('#tree').jstree(true).settings.core.data = jsonData;
$('#tree').jstree(true).deselect_node(this);
$('#tree').jstree(true).toggle_node(this);
$('#tree').jstree(true).refresh();
}
},
contentType: "application/json"
});
},
onClickFunctionNode: function(node) {
Tree.treeDivIdSelector.jstree(true).toggle_node(node);
},
pluginsArray: ["search", "checkbox", "types", "json_data","html_data"],
treeMenuContextItems: {},
Init: function(initData) {
Tree.dataJson = initData.dataJson;
Tree.treeDivIdSelector = initData.chartDivId;
Tree.searchDivIdSelector = initData.searchDivId;
var apiUriTree = 'api/TreeCustomChildren.aspx';
Tree.treeDivIdSelector.jstree({
"checkbox": {
"keep_selected_style": true,
"three_state": false
},
"plugins": Tree.pluginsArray,
'core': {
'data': function (node, cb) {
// Fetch tree custom parent nodes
if (node.id === "#") {
cb(Tree.dataJson);
}
else {
var _cb = cb;
//Fetch tree custom Child nodes
var TreeCustomApiRequest = {
nUserId: document.getElementById("TrendUserID").value,
nAccessLevel: document.getElementById("hfTrendAccessLevel").value,
nTreeCustomParentId: node.id
}
function recieveData(data) {
cb(data);
}
$.ajax({
type: "POST",
data: JSON.stringify(TreeCustomApiRequest),
url: apiUriTree,
success: recieveData,
contentType: "application/json"
});
}
},
"themes": {
"icons": false
}
},
"contextmenu": {
items: Tree.pluginsArray.indexOf("contextmenu") > -1 ? Tree.treeMenuContextItems : null
}
});
var tree = Tree.treeDivIdSelector.jstree();
function getNode(sNodeID) {
return tree.get_node(sNodeID);
}
Tree.treeDivIdSelector.on('click', '.jstree-anchor', function(e) {
Tree.onClickFunctionNode(this);
}
);
//Tree.searchDivIdSelector.keyup(Tree.searchFunction);
},
The next code is in the client side......
<script type="text/javascript">
$(document).ready(function () {
var dataJson = <%=sTreeViewJson%>
Tree.Init({ dataJson: dataJson, chartDivId: $("#tree") });
$("#btnSearch").click(function () {
// Do the Ajax search
Tree.searchAjaxFunction();
//var value = document.getElementById("tree_search").value;
//Tree.searchFunction();
})
});
</script>
Thank you Nikolay, it was a stupid mistake from me so what I added was just this to my code:
success: function (jsonData, callback )
{
//Goes back to the Callback with the new search data
Tree.Init({ dataJson: jsonData, chartDivId: $("#tree"), searchDivId: $("#tree_search") });
$('#tree').jstree(true).refresh();
}
So I removed the
$('#tree').jstree(true).settings.core.data = jsonData;
$('#tree').jstree(true).deselect_node(this);
$('#tree').jstree(true).toggle_node(this);
Know it gets my data and refreshes the table with the init function while it has my new data.
Hope this also may help someone = ).

Backbone.js custom model request

Is there any way to create your own ajax method to make a POST request instead of using save ?
Save not only fires the AJAX request but triggers events and validation, so I wouldn't write my "own" save method.
However, you can always write a model function like:
var SomeModel = Backbone.Model.extend({
urlRoot: "/some/url",
altSave: function () {
$.post(this.urlRoot, {
/*assemble your post data*/
}, function (response) {
});
}
});
var s = new SomeModel();
s.altSave();
calling s.altSave(); will fire a POST request.
That's right and it works but I think this is a better solution:
'use strict';
define([
'underscore',
'backbone',
'config/appConfig'
],function(_,Backbone,Config){
var StatsModel = Backbone.Model.extend({
urlRoot: Config.urlStats,
url: function() {
var url = this.urlRoot + "/resource";
return url;
},
defaults: {
metricID: '',
groupByID: ''
},
requestStats: function(opts) {
var url = this.url(),
options = {
url: url,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(this.attributes)
};
_.extend(options, opts);
return (this.sync || Backbone.sync).call(this, null, this, options);
}
});
return StatsModel;
});
Thank you very much

Backbone collection not triggering add event on fetch

I have been banging my head against a wall for hours on this one....
Looked at many-a-page and I feel like I have my script correct, but my collection is not triggering an add event with add: true passed in the fetch method. I can bind to the reset event, but the add event doesn't trigger..
Model:
test.Models.AppBlock = Backbone.Model.extend({
defaults: {
AppID: null,
AppName: null,
AppDescription: null
},
idAttribute: "AppID"
});
Collection:
test.Collections.AppBlock = Backbone.Collection.extend({
model: test.Models.AppBlock,
url: ApiPath + "apps/byuser",
Loading: false,
initialize: function () {
},
getAppBlocks: function () {
if (!this.Loading) {
this.Loading = true;
this.fetch({
data: JSON.stringify({
Token: test.Session.Token
}),
add: true, // OMG WTF ?!?!
type: 'POST',
dataType: 'json',
contentType: 'application/json',
cache: false,
success: this.getAppBlocksSuccess,
error: this.getAppBlocksError
});
}
},
parse: function (response) {
return response.Data;
},
getAppBlocksSuccess: function (that, response) {
},
getAppBlocksError: function (that, response) {
}
});
View:
test.Views.DashboardLatestMain = Backbone.View.extend({
Loading: null,
initialize: function () {
this.template = _.template(test.Templates.DashboardLatestMain);
this.collection.bind('add', this.addAppBlock);
this.render();
},
render: function () {
$('#latest').prepend(this.template);
this.Loading = new test.Views.Loading({
el: '.main'
});
this.collection.getAppBlocks();
},
addAppBlock: function (appBlockModel) {
alert(appBlockModel); // no dice....
var appBlockView = new test.Views.AppBlock({
model: appBlockModel,
el: '#latest .main h3',
After: true
});
}
});
Any help is greatly appreciated.
edit
Data returned from api:
{
"Status":["1","OK"],
"Data":[{"AppID":1,"AppName":"test","AppDescription":"test"},
{"AppID":2,"AppName":"test","AppDescription":"test"}]
}
In Backbone 0.9.9 collection's fetch did a reset by default, which triggered only the 'reset' event. In 1.0, fetch does an update (now called set), and triggers 'add', 'remove' and 'change' events by default.
So, either update to 1.0 and your existing code should work. Or, add update:true to your fetch call (you don't need add:true then because that is the default).

Using backbone.js to get data from ASMX with the 'd'

I'm pretty new to Backbone and I've been trying to create autocomplete functionality with it, fed by an ASMX webservice. The issue I seem to have is whilst my webservice returns in JSON (after a painful battle with it), it wraps the response in a 'd' (dataset). How do I get the view to understand this and get at the correct data?
Here is my code:-
var Airline = Backbone.Model.extend({
initialize: function () {},
defaults: {
name: 'Airline Name',
rating: 50,
icon: '/blank.png'
}
});
var AirlineCollection = Backbone.Collection.extend({
model: Airline,
contentType: "application/json",
url: '/ControlTower/public/runway.asmx/all-airlines',
parse: function (response) {
return response;
}
});
var SelectionView = Backbone.View.extend({
el : $('#airline'),
render: function() {
$(this.el).html("You Selected : " + this.model.get('AirlineName'));
return this;
},
});
var airlines = new AirlineCollection();
airlines.fetch({async: false, contentType: "application/json" });
var airlineNames = airlines.pluck("AirlineName");
$("#airline").autocomplete({
source : airlineNames,
minLength : 1,
select: function(event, ui){
var selectedModel = airlines.where({name: ui.item.value})[0];
var view = new SelectionView({model: selectedModel});
view.render();
}
});
Can anyone see what I'm doing wrong? I've been sitting here for too long now!
Help is appreciated ;)
What about in your AirlineCollection:
parse: function (response) {
return response.d;
}
This works for me
In AirlineCollection
parse: function (response) {
var data = (typeof response.d) == 'string' ? eval('(' + response.d + ')') : response.d;
return data;
}

Categories

Resources