Been some time since I last looked at Angularjs. I have a simple get that calls an ASP.NET Controller and returns a Json object - the get is triggered but nothing is getting populated on the view. The Json object shows in the browser, so it's purely a JS Angular thing. I know I am missing something simple, but I can't quite put my finger on it. If someone would be kind enough to show what I'm missing preferably with an example that would great. I haven't been able to find a simple example, that's similar.
Angularjs.
var ngCurrent = angular.module("ngCurrent", ['ngResource']);
var ctrCd;
// Declaring a Service
ngCurrent.factory("CurrentService", function ($resource) {
return {
data: $resource("/Current/Data/:id")
}
});
ngCurrent.controller("CurrentController", function ($scope, CurrentService) {
$scope.current = CurrentService.data.get({ "id": id}, isArray = false);
});
In the CSHTML View (Condensed but all relevant rows included)
<div ng-app="ngCurrent" class="row">
<div ng-controller="CurrentController" class="col-md-1"></div>
<div class="row">
<span class="col-sm-2">{{current.RecordName}}</span>
It runs triggers the "Get" from the controller but displays no data and $scope.current contains no object.
I have had a go at JSFiddling without success here it is http://jsfiddle.net/Mark_Dete/Lfy66re1/1/
(note the Json mocking is based on http://jsfiddle.net/ExpertSystem/6PYsq/)
You can return a promise from your service like:
return $http({
url: '/api/v1/service/',
method: "GET",
headers: {'X-API-TOKEN': api_key },
params: _params
})
Then use the promise callbacks on the http object in your controller (the one returned from your service)
$scope.getApiData = function(){
Service.getData($scope.api_key)
.then(function(_data) {
console.log(_data.data);
$scope.data_obj = _data.data;
});
here's an all in one version without the service abstraction but it should work for testing.
$scope.getApiData = function(){
$http({
url: '/api/v1/service/',
method: "GET",
headers: {'X-API-TOKEN': api_key },
params: _params
})
.then(function(_data) {
console.log(_data.data);
$scope.data_obj = _data.data;
});
Make sure you remember to inject the $http dependency!
Related
i have simple code in meteor js for find near by garages within 10 Kilometres the query works fine in my mongodb database if run it manually in robomongo it works fine but when i run it in my routes it throws an error. like this.
Error: Unrecognized operator: $nearSphere in meteor jsi
i see some blogs they said you need to call a server side method for this. so i use below code to call a server side route.
Router.route('/search/:name',
{name:'searchlist',
data:function(){
var searchedParams = this.params.name.split('-');
var lat = searchedParams.pop();
var lng = searchedParams.pop(1);
return {searchValue: Centers.find({ coordinates: { $nearSphere: { $geometry: { type: "Point", coordinates: [lng,lat] }, $maxDistance: 10000 } } })}
}
}, { where: "server" }
);
if anyone have idea please help.
You're mixing definitions for client and server side routes.
Server-side route should look like this:
Router.route('/search/:name', function(...){...}, { where: 'server' });
Client-side route could look like this:
Router.route('/search/:name, { ... });
Thus, your route is actually client-side route and minimongo doesn't have support for $nearSphere operator as noted here: https://github.com/meteor/meteor/blob/devel/packages/minimongo/NOTES
First, look at Styx answer and make the route a client route by eliminating this part:
', { where: "server" }'
Now that the router is available to the client, let's fix the $nearSphere issue, by changing the operator to $near. Use the following code:
Centers.find(
{
geoloc: {
$near: {
$geometry: {
type: "Point",
coordinates: [lng, lat]
}
}
}
}
);
Give it a try and let me know if it works.
It's evident how to provide route-specific data, i.e. through the use of a controller:
PostController = RouteController.extend({
layoutTemplate: 'PostLayout',
template: 'Post',
waitOn: function () { return Meteor.subscribe('post', this.params._id); },
data: function () { return Posts.findOne({_id: this.params._id}) },
action: function () {
this.render();
}
});
But how does one provide data for the application in general? In the case that every route needs to be subscribed to the same subset of information, so that the pub/sub doesn't need to be re-done on every route change. Thanks!
It sounds to me like you are looking for a completely general publication/subscription scheme so that you do not have to define the waitOn/data option combination for every single route or route controller that you define. In that case, you can simply publish a given set of data on the server like so:
Meteor.publish('someData', function() {
return SomeDataCollection.find({});
});
and subscribe to that set of data on the client like so:
Meteor.subscribe('someData');
With this publication/subscription pair setup, you will have access to the data provided in all routes. You just have to make sure that you check for non-existent data in your code to handle the first load of any given template when the data has not been loaded on the client yet. In this manner, you would never have to actually define a the waitOn and data options for any route or route controller.
If you would like to utilize Iron Router in a different way than through route controllers, you also have the option of waiting on one/many subscriptions globally by using the Router.configure({}); function. To use the example above:
Router.configure({
waitOn: function() {
return Meteor.subscribe('someData');
}
});
For information about this route option and all of the other options that you have available at a global level, check this out.
I want to use a reactive counter var on server side. But I can not guess how to do it without using collections.
I expect {{count}} will be updated after server count var changed without refresh a page or how to send a client that the count was changed?
<body>
{{> test }}
</body>
<template name="test">
{{count}}
</template>
client:
Meteor.call('count', function(err, result) {
console.log(result)
Session.set('count', result)
})
Template.test.helpers({
count: function () {
return Session.get('count')
}
});
server:
var count=0
Meteor.startup(function () {
Meteor.setInterval(function() {
count++
}, 1000)
});
Meteor.methods({
count: function() {
return count
}
})
My code on MeteorPad
I want to see what I expect:
Client:
Meteor.subscribe('count')
Template.test.helpers({
count: function () {
return Counter.findOne().count
}
});
Common:
Counter = new Mongo.Collection('count')
Server:
Meteor.publish('count', function() {
return Counter.find()
})
Meteor.startup(function () {
if(Counter.find().count() === 0) {
Counter.insert({count: 0})
}
Meteor.setInterval(function() {
Counter.update({}, {$inc: {count: 1}})
}, 1000)
});
Example on meteorpad
It depends on how you plan to scale your application. If you plan to scale to multiple server instances then you cannot rely on the servers sharing information automatically. In this case it would be best to create a collection named something like "ApplicationState". Then every instance of your application can use a consistent state, and you can make use of the built in subscriptions.
If you plan to only use a single server instance then you should checkout the documentation on Tracker: http://manual.meteor.com/#tracker. This allows you to defined custom dependencies on data. I have not had the chance to play with it yet, but I am pretty sure that you can create something similar to subscriptions: http://manual.meteor.com/#deps-creatingreactivevalues
Your code does not work as the way you want it because regular plain vars are not reactive data sources. The docs has a list of reactive data sources here http://docs.meteor.com/#/full/reactivity - So for your example to work you'd want to use Session or ReactiveVar - but these only works on the client so they wont help you here.
Your best bet is to create a manual publish function and subscribe to it from the client (or as other people has proposed, use a Collection - which would work across multiple servers as well). Hope that helps!
I have a simple list and details view using two collections.
When I navigate back to the list view Meteor removes the single document added to the details collection and undoes the change to the other collection.
I want this data to remain so the client doesn't have to keep reloading it...
Both the 'league' and the 'standings' subscriptions are 'undone' on navigation back to the the root. The league and leagues route both use the 'weeks' Mongo collection. When navigating to a league detail I add to the single document. Navigation to the detail works fine ... its when I navigate back to the list that I loose the collection data.
I need all this data 'cached' and am obviously not going about it correctly....
Router.map(function () {
this.route('leagueList', {
path: '/'
});
this.route('league', {
path: '/league/:league',
template: 'standings',
waitOn: function () {
console.log(this.params.league);
return [Meteor.subscribe('league', this.params.league),
Meteor.subscribe('standings', this.params.league) ];
},
data: function () {
return {theLeague: Leagues.findOne({league: this.params.league}),
theStandings: Standings.findOne()};
}
});
});
Server:
Meteor.publish('leagues', function(){
console.log('all league names sent');
return Leagues.find({}, {fields: {weeks: 0}});
});
Meteor.publish('league', function(theLeague){
console.log('sending weeks detail for: ' + theLeague);
return Leagues.find({league: theLeague});
});
Meteor.publish('standings', function(theLeague){
console.log('standings: ' + theLeague);
var file = Leagues.findOne({league: theLeague}).weeks[0].file;
return Standings.find({file: file});
});
client:
Leagues = new Meteor.Collection('weeks');
Standings = new Meteor.Collection('details');
Meteor.subscribe('leagues');
There's work in progress in iron router to allow (and optimize) this (not immediately stopping the subscriptions when you route to another page). See the sub-manager branch.
But if you create the subscription apart from the waitOn call, I think the subscription is never stopped. For example, in the code below, the routes a and c will wait for the initialData to be received (which will be fetched directly when the user loads the page (even if it uses route b)), and the subscription for it will never stop, even if you leave, for example, route a. However, I don't think you can use this approach if you need to use some parameters in the route (you can probably fix something with setInterval, but it will be ugly).
var handleToDataIMostlyNeed = Meteor.subscribe('initialData')
Router.map(function(){
this.route('a', {
waitOn: function(){
return handleToDataIMostlyNeed
}
})
this.route('b', {
waitOn: function(){
return [] // Wait for nothing.
}
})
this.route('c', {
waitOn: function(){
return handleToDataIMostlyNeed
}
})
})
Hi this is my first attempt to use MustacheJS with a JSON webservice in .net
Currently I am struggling I can't seem to find what I am doing wrong setting this basic example:
My Webservice is returing the following string:
[
{
"ShortDescription":"BOX",
"Description":"BOXING",
"Id":1
},
{
"ShortDescription":"EPL",
"Description":"ENGLISH PREMIER LEAGUE",
"Id":2
}
]
I have validated its syntax with this website: http://json.parser.online.fr/
and here is the HTML code I am using:
google.load("jquery", "1");
google.setOnLoadCallback(function () {
$(document).ready(
function () {
$.ajax({
url: "../data.asmx/geteagues",
type: "POST",
dataType: "json",
data: "",
contentType: "application/json; charset=utf-8",
success: function (data) {
var template = "<h1>{{ShortDescription}} {{Description}}</h1>";
var html = Mustache.render(template, data);
$('#sampleArea').html(html);
alert(html);
}
})
}
)
});
I am posting the whole JS code, since I am not very good with javascript, basically I want to load always the latest JQuery version from google and then work my WS call.
The problem so far is that when I place a breakpoint in the following line:
var html = Mustache.render(template, data);
I see that the template is setn ok, and so does the data, same value as I posted above, but the .render function is returning: I seems It didnt like the data.
So far all the examples I have seen for inline data come as the following structure:
{
"repo": [
{ "name": "resque" },
{ "name": "hub" },
{ "name": "rip" },
]
}
And then a template defined like this:
{{#repo}}
<b>{{name}}</b>
{{/repo}}
But the only difference of that against my data is that I dont have a "parent" like "repo"
At server side, I am using a .net library called JSON.net and in the documentation of how are collections being serialized:
james.newtonking.com/projects/json/help/html/SerializingCollections.htm
the final result does not include the parent node's name, which I thing is missing from my Mustache Template definition:
[
{
"Name": "Product 1",
"ExpiryDate": "2000-12-29T00:00Z",
"Price": 99.95,
"Sizes": null
},
{
"Name": "Product 2",
"ExpiryDate": "2009-07-31T00:00Z",
"Price": 12.50,
"Sizes": null
}
]
Is this what I am missing? the "repo" parent node from my data so I can iterate my Template?
Thanks in advance for your time.
-ed
Per #stealth on this question Mustache.js: Iterate over a list received via json
{{ #. }}
<b>{{Name}}</b>
{{ /. }}
Note the only difference from #stealth's answer is a "#" instead of "/".
The line data = { 'roles': data }; is the most crucial. Its attaching the key to the data returned by web api or any other source of data like pagemethods or web service
$.ajax({
dataType: "json",
url: '/api/TestApi/GetAllRole',
success: function (data) {
data = { 'roles': data }; // formatting the data to support the mustache format
var html = Mustache.to_html($('#RoleTemplate').html(), data);
$('#tblRole').append(html);
}
});
Few of my articles on the MustacheJs can be found here
INLINE FILTER FOR BASIC GRID USING MUSTACHEJS
http://www.techguides.in/add-inline-filter-to-basic-grid-using-mustache/
Master Details Grid on Demand data loading : Using Mustache.JS
http://www.techguides.in/master-details-grid-on-demand-data-loading-using-mustache-js/
Sorting a Grid using MustacheJs
http://www.techguides.in/enable-sorting-in-a-grid-bound-using-mustache-js/
short answer: YES
long answer: for security reasons [1], you need to wrap your JSON aray in an object anyways. for Mustache or any other library to be able to access your array you need to have at least one parent key on which you can base your iterator.
The "repo" key on your sample is the helper you need to tell mustache "go and iterate on the array that is inside the repo key", otherwise you have no way to tell the template what you want to output where
[1] this is just one of many resources you can find about why you need to wrap your JSON response in an object http://incompleteness.me/blog/2007/03/05/json-is-not-as-safe-as-people-think-it-is/