json data not rendered in backbone view - json

I have been trying to render the json data to the view by calling
the rest api and the code is as follows:
var Profile = Backbone.Model.extend({
dataType:'jsonp',
defaults: {
intuitId: null,
email: null,
type: null
},
});
var ProfileList = Backbone.Collection.extend({
model: Profile,
url: '/v1/entities/6414256167329108895'
});
var ProfileView = Backbone.View.extend({
el: "#profiles",
template: _.template($('#profileTemplate').html()),
render: function() {
_.each(this.model.models, function(profile) {
var profileTemplate = this.template(this.model.toJSON());
$(this.el).append(tprofileTemplate);
}, this);
return this;
}
});
var profiles = new ProfileList();
var profilesView = new ProfileView({model: profiles});
profiles.fetch();
profilesView.render();
and the html file is as follows:
<!DOCTYPE html>
<html>
<head>
<title>SPA Example</title>
<!--
<link rel="stylesheet" type="text/css" href="src/css/reset.css" />
<link rel="stylesheet" type="text/css" href="src/css/harmony_compiled.css" />
-->
</head>
<body class="harmony">
<header>
<div class="title">SPA Example</div>
</header>
<div id="profiles"></div>
<script id="profileTemplate" type="text/template">
<div class="profile">
<div class="info">
<div class="intuitId">
<%= intuitId %>
</div>
<div class="email">
<%= email %>
</div>
<div class="type">
<%= type %>
</div>
</div>
</div>
</script>
</body>
</html>
This gives me an error and the render function isn't invoking
properly and the render function is called even before the REST
API returns the JSON response.
Could anyone please help me to figure out where I went wrong. Any help is highly appreciated
Thank you

Firstly, you need to pass the model attributes to the template function explicitly. So change the appropriate code in the view to:
var ProfileView = Backbone.View.extend({
el: "#profiles",
//template: _.template($('#profileTemplate').html()), REMOVED
render: function() {
_.each(this.model.models, function(profile) {
var profileTemplate = _.template($('#profileTemplate').html(), {
intuitId: profile.get("intuitId"),
email: profile.get("email"),
type: profile.get("type")
});
$(this.el).append(tprofileTemplate);
}, this);
return this;
}
});
Secondly, your render method is not dependent on the fetch response from being returned from the server. It will get called immediately after the line above it executes and not wait for the fetch response. This behavior you are experiencing is by design. If you want to call render after you get the response back from the server you'll have to use events. You could replace profilesView.render(); with something like:
profilesView.listenTo(profiles, "sync", profilesView.render);
This means that the profilesView will listen for the profiles collection to complete its fetch and fire a sync event. When this occurs, the render function of the view will be called.

Related

AngularJS databinding through responsemessage not working as expected

Code is as follows
var myApp = angular.module("gameModule", []);
myApp.controller("gamecontroller", function ($scope) {
$scope.message = "test";
// websocket connection.
var gameHub = $.connection.socketHub;
$.connection.hub.start().done(function () {
var clientid = $.connection.hub.id;
$(function () {
var user = { signalrsessionid: clientid };
$.ajax({
type: "POST",
data: JSON.stringify(user),
url: "http://localhost:53629/api/game/signalr",
contentType: "application/json"
}).done(function (response) {
alert(response);
$scope.responsemessage = response;
});
});
});
});
and front end code
<!DOCTYPE html>
<html ng-app="gameModule">
<head>
<title>game registration</title>
<meta charset="utf-8" />
<script src="Scripts/jquery-1.10.2.js"></script>
<script src="Scripts/jquery.signalR-2.2.1.js"></script>
<script src="Scripts/angular.js"></script>
<!--Automatisch gegenereerde signalR hub script -->
<script src="signalr/hubs"></script>
<script src="Scripts/rouletteAngular.js"></script>
</head>
<body>
<div ng-controller="gamecontroller">
{{ message }}
{{ responsemessage }}
</div>
So the 'message' is being displayed, the alert box with the response is showing the correct response, but the responsemessage doesnt show any value.
Can anyone tell me what i'm doing wrong.
you must call $scope.$apply(); or $scope.$digest(); after setting $scope.responsemessage = response; because you are using jQuery ajax call, which is outside Angulars context.
EDIT:
here you have nice way to use SignalR in AngularJS:
http://henriquat.re/server-integration/signalr/integrateWithSignalRHubs.html

Add sort to Angular factory

I want to add a sort function to my factory controller in Angular JS.
I have got as far as what I have below:
var albumsApp = angular.module ('albumsApp',[])
albumsApp.factory('albumFactory',function($http) {
return {
getAlbumsAsync: function(callback,$scope){
$http.get('albums.json').success(callback);
},
};
});
albumsApp.controller ('albumController', function ($scope,albumFactory) {
albumFactory.getAlbumsAsync(function(results){
console.log('albumController async returned value');
$scope.albums = results.albums;
});
albumFactory.changeSorting(function(results){
console.log('changeSorting called');
});
});
I get an error "TypeError: albumFactory.changeSorting is not a function" (this refers to the albumFactory.changeSorting) as I have not added it to the factory. I don't know how to do this.
The html code I am using is below: I want to call the function to sort what is in the JSON file alphabetically
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="js/angular.js"></script>
<script src="js/angular-route.js"></script>
<script type="text/javascript" src="modules/app.js" ></script>
</script>
<title>
</title>
</head>
<body ng-app="albumsApp">
<div data-ng-controller="albumController">
<!-- <ul data-ng-repeat="album in albums| orderBy:'title'"> -->
<ul data-ng-repeat="album in albums">
<li>
Artist is "{{album.artist}}" and title is "{{album.title}}"
</li>
</ul>
<button data-ng-click="changeSorting()">Description</button>
</div>
</body>
</html>
The JSON list is below:
{
"albums":[
{
"artist": "Arctic Monkeys",
"title": "AM"
},
{
"artist": "Nirvana",
"title": "Nevermind"
},
{
"artist": "Buck 65",
"title": "Man Overboard"
}
]
}
Your view is not directly connected to the Angular service—all methods called from the view should be in your controller. You should have a method on your controller and not in your factory. Try moving that function to your controller:
albumsApp.controller ('albumController', function ($scope,albumFactory) {
albumFactory.getAlbumsAsync(function(results){
console.log('albumController async returned value');
$scope.albums = results.albums;
});
$scope.changeSorting = function (){
// your logic goes here
console.log('changeSorting called');
});
});
You can keep your logic in your controller. You can use orderBy in Angular's $filter module to help you sort:
$filter('orderBy')(array, expression, reverse)

Autocomplete for textbox in mvc

This is my view and controller. I have converted code from c# to vb the code was working perfectly in C# but i dont know why this java script is not working in vb. I started debugging but controllers never get called when i type something in search box.
Code for View
#ModelType PrudentHealthCare.Product
#Code
Layout = Nothing
End Code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Search</title>
</head>
<body>
<div>
#Using (Html.BeginForm())
#Html.HiddenFor(Function(model) model.id)
#<input type="text" id="search" placeholder="Search for a product" required />
#<input type="submit" value="Go" id="submit" />
End Using
</div>
</body>
</html>
<link href="~/Content/AutoComplete/jquery-ui.css" rel="stylesheet" />
<script src="~/Content/AutoComplete/jquery-ui.js"></script>
<script src="~/Content/AutoComplete/jquery-1.9.1.js"></script>
<script type="text/javascript">
var url = '#Url.RouteUrl( "DefaultApi" , New With { .httproute = "", .controller = "ProductApi" })';
$('#search').autocomplete({
source: function (request, response) {
$.ajax({
url: url,
data: { query: request.term },
dataType: 'json',
type: 'GET',
success: function (data) {
response($.map(data, function (item) {
return {
label: item.Description,
value: item.Id
}
}));
}
})
},
select: function (event, ui) {
$('#search').val(ui.item.label);
$('#Id').val(ui.item.value);
return false;
},
minLength: 1
});
</script>
ProductApiController
Imports System.Web.Mvc
Namespace Controllers
Public Class ProductApiController
Inherits Controller
<HttpGet>
Public Function GetProducts(Optional query As String = "") As IEnumerable(Of Product)
Dim xyz As String
xyz = query
End Function
End Class
End Namespace
jQuery UI has an AutoComplete widget. The autocomplete widget is quite nice and straight forward to use. In this post, how to integrate the AutoComplete widget with an ASP.NET MVC application.
The first step is to add the jQuery scripts and styles. With ASP.NET MVC 4, the following code does the work:
#Styles.Render("~/Content/themes/base/css")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryui")
Using the AutoComplete widget is also simple. You will have to add a textbox and attach the AutoComplete widget to the textbox. The only parameter that is required for the widget to function is source. For this example, we will get the data for the AutoComplete functionality from a MVC action method.
$(document).ready(function () {
$('#tags').autocomplete(
{
source: '#Url.Action("TagSearch", "Home")'
});
})
In the above code, the textbox with id=tags is attached with the AutoComplete widget. The source points to the URL of TagSearch action in the HomeController: /Home/TagSearch. The HTML of the textbox is below:
<input type="text" id="tags" />
When the user types some text in the textbox, the action method - TagSearch is called with a parameter in the request body. The parameter name is term. So, your action method should have the following signature:
public ActionResult TagSearch(string term)
{
// Get Tags from database
string[] tags = { "ASP.NET", "WebForms",
"MVC", "jQuery", "ActionResult",
"MangoDB", "Java", "Windows" };
return this.Json(tags.Where(t => t.StartsWith(term)),
JsonRequestBehavior.AllowGet);
}

SAPUI5 - Login Page

I'm building an app that communicates with an IBM software through REST.
The thing is that I have a POST Method in the NewTicket.controller, but I need to use the user and password on this method to open the ticket.
How can I send the variables (or other thing) that I have on my Login.controller to the NewTicket.controller?
This is my Post Method:
enviar:function() {
var description = this.byId("desc").getValue(); //Recebe o resumo
var long_description = this.byId("long_desc").getValue(); //Recebe a descrição
jQuery.sap.require("sap.m.MessageToast");
sap.m.MessageToast.show(user);
jQuery.sap.require("sap.m.MessageBox");
// open a fully configured message box
sap.m.MessageBox.show("Confirmar a abertura do chamado?",
sap.m.MessageBox.Icon.QUESTION,
"Confirmar",
[sap.m.MessageBox.Action.YES, sap.m.MessageBox.Action.NO],
function(sResult) {
if(sResult == sap.m.MessageBox.Action.YES) //Se clicar em SIM (popup com numero do chamado e tela com lista)
{
var oModel = new sap.ui.model.json.JSONModel();
var url = "http://xxx.xxx.xxx.xx:xxxx/maxrest/rest/mbo/sr/?_lid=" + **user** + "&_lpwd=" + **password** +"&description="+ description +"&description_longdescription=" + long_description + "&_format=json&_compact=true&_verbose=true";
var aData = jQuery.ajax({
type : "POST",
contentType : "application/json",
url : url,
dataType : "json",
async: false,
success : function(data,textStatus, jqXHR) {
oModel.setData({modelData : data});
sap.m.MessageBox.show("ABRIU");
},
error : function(data,textStatus, jqXHR) {
oModel.setData({modelData : data});
sap.m.MessageBox.show(textStatus);
}
})}
else // Se clicar em NÃO
{
}
},
sap.m.MessageBox.Action.YES);
Thank you in advance.
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<script src="resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_bluecrystal">
</script>
<script>
sap.ui.localResources("app");
var app = new sap.m.App({initialPage:"idinitial1"});
var page = sap.ui.view({id:"loginPage", viewName:"app.login", type:sap.ui.core.mvc.ViewType.XML});
app.addPage(page);
app.placeAt("content");
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
login.view.xml
<core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
controllerName="app.login" xmlns:html="http://www.w3.org/1999/xhtml">
<Page title="Title">
<content>
<Panel headerText = "example" expandable = "true" expanded = "true">
<content>
<Input id="userID" value="User123"/>
<Button text="Login" press="btnClicked"/>
</content>
</Panel>
</content>
</Page>
</core:View>
login.controller.js
sap.ui.controller("app.login", {
btnClicked: function(){
this.userName = this.byId('userID').getValue();
//loading the second view but not placed anywhere, just for showing code usage
sap.ui.view({id:"myTickePage", viewName:"app.ticket", type:sap.ui.core.mvc.ViewType.JS});
}
});
ticket.view.xml can be anything but inside ticket.controller.js:
onInit: function() {
var user = sap.ui.getCore().byId('loginPage').getController().userName;
console.log(user);
},
Output:
Define a variable under the controller scope of Login.controller.
Eg: In Login.controller have a variable this.myValue
In MyTicket.controller:
sap.ui.getCore().byId('loginViewID').getController().myValue
This will work as long as your login view/controller are not destroyed.
Suppose two views:
login view corresponding to Login.controller (viewid_login)
ticket view corresponding to NewTicket.controller (viewid_ticket)
In Login.controller:
onInit: function() {
this.userName= "User123";
},
In NewTicket.controller:
onInit: function() {
var user = sap.ui.getCore().byId('viewid_login').getController().userName;
//this will return "User123"
},
Hope this makes it clear.
Note that your login view should not be destroyed.
Depends where you are storing the user and password. The correct way would be to actually store them in the model. Initialize the model on the onInit and then get them when you need them.
onInit: function() {
..
var data = {user: 'bla', password: 'ble'};
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
sap.ui.getCore().setModel(oModel);
..
}
then on the view you can get the values with:
var oModel = sap.ui.getCore().getModel();
var data = oModel.getData();
//data.password
//data.user

Fetching directory contents to json in backbone

I have folder that contains images; I call fetch on the folder uploads/ and my GET returns with the following response in HTML (no json etc)
<h1>Index of /backbone_images/uploads</h1>
<ul><li> Parent Directory</li>
<li> 2012-12-11 15.30.221.jpg</li>
<li> in1.jpg</li>
<li> imagedummy.png</li>
I try to render / my fetched data into models etc with the following code:
window.Person = Backbone.Model.extend({});
window.AddressBook = Backbone.Collection.extend({
url: 'uploads/',// declare url in collection
model: Person
});
window.Addresses = new AddressBook();
window.AppView = Backbone.View.extend({
el: $('#left_col'),
initialize: function() {
Addresses.bind('reset', this.render); // bind rendering to Addresses.fetch()
},
render: function(){
console.log(Addresses.toJSON());
}
});
window.appview = new AppView();
Addresses.fetch();
but nothing is being rendered or appended to my left column: so --> can I fetch from a directory containing images like this? Also what can I do with the HTML response and how can I load it into models, make it render etc (if there is any way) ?
You should change the HTML response into a JSON format so Backbone can render it properly (although there's a way to display the HTML you have above, this isn't a recommended approach as it's better to render raw data).
You can do something like this:
HTML:
<div id="container">
</div>
<script id="template" type="text/html">
<li><img src=<%- dir %><%- image %> /></li>
</script>
JavaScript:
$(function(){
/** Your response object would look something like this. */
var json = {'parent_directory':
{'dir_desc': 'Index of /backbone_images/uploads',
'images': [
{'dir': '/images/', 'image': 'image1.jpg'},
{'dir': '/images/', 'image': 'image2.jpg'},
{'dir': '/images/', 'image': 'image3.jpg'}
]
}};
/** Create a simple Backbone app. */
var Model = Backbone.Model.extend({});
var Collection = Backbone.Collection.extend({
model: Model
});
var View = Backbone.View.extend({
tagName: 'ul',
initialize: function() {
this.render();
},
template: _.template($('#template').html()),
render: function() {
_.each(this.collection.toJSON(), function(val){
this.$el.append(this.template({
image: val.image,
dir: val.dir}));
}, this);
return this;
}
});
/** Create a new collection and view instance. */
var newColl = new Collection(json.parent_directory.images);
var newView = new View({collection: newColl});
$('#container').html(newView.el);
});
You should bind it to the sync event
Also I prefer to use listenTo
this.listenTo(Addresses, 'sync', this.render)