Scope data seem empty after putting json in it - asp.net

I'm trying to get some data from an API in the variable $scope.proposition with the following code
'use strict';
var app = angular.module('app', []);
app.controller('propositionCtrl',['$scope', 'propositionRepository',
function ($scope, propositionRepository) {
// $scope.proposition = { marge_propose: 3 };
function getProposition() {
propositionRepository.getProposition(function (result) {
$scope.proposition = result;
console.log("we put the json in the scope variable");
}
)
}
getProposition();
$scope.proposition = {marge_propose : 3};
}])
app.factory('propositionRepository', function ($http) {
return {
getProposition: function (callback) {
$http.get('/api/propositionapi/3');
console.log("we call the api");
}
}
})
With the following view
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div ng-controller="propositionCtrl">
<p>{{ proposition.marge_propose}}</p>
</div>
It does not work, but when I uncomment the $scope.proposition = { marge_propose: 3 }; everything works just fine.
That's why I assume that it is my getProposition that encounters some problems.
I don't know what it is because firebug actually tells me that the data are well received from the api with the following result
{"$id":"1","t_concours":{"$id":"2","t_proposition":[{"$ref":"1"}],"id":1,"intitule":"test","valeur":10.0},"t_demandeur":{"$id":"3","t_proposition":[{"$ref":"1"}],"id":"1","nom":"dylan","prenom":"bob","note":"A"},"t_index":{"$id":"4","t_proposition":[{"$ref":"1"}],"id":1,"intitule":"test","valeur":10.0},"t_proposition_concurence":null,"id":3,"id_demandeur":"1","date_proposition":"1991-07-05T00:00:00","type":true,"point_de_vente":"01","code":"a","code_sas":"846684","montant_operation_hors_frais":200,"concours_sollicite":10,"duree_concours":10,"type_concours":1,"id_index":1,"apport_personnel":10,"garantie_reelle":true,"in_fine":false,"majoration":1.0,"prospect":true,"primo_accedant":true,"motif_montant":false,"motif_contrepartie":false,"motif_depot_cmne":false,"id_prop_concurence":null,"motif_autre":true,"motif_commentaire":"true","proposition_derogatoire":true,"visa_responsable":"false","marge_grille":5.0,"marge_theorique":7.0,"marge_propose":32.0}
Can someone explain me please where the problem is?
Thanks a lot!
EDIT:
The console log displays "we call the api" but not "we put the json in the scope variable"

'use strict';
var app = angular.module('app', []);
app.controller('propositionCtrl',['$scope', 'propositionRepository',
function ($scope, propositionRepository) {
// $scope.proposition = { marge_propose: 3 };
function getProposition() {
propositionRepository.getProposition(function (result) {
console.log("we put the json in the scope variable");
$scope.proposition = result;
}
)
}
getProposition();
$scope.proposition = {marge_propose : 3};
}])
app.factory('propositionRepository', function ($http) {
return {
getProposition: function (callback) {
$http.get('/api/propositionapi/3').success(callback);
console.log("we call the api");
}
}
})
This code works...
The thing is that I didn't know that $http.get returns a promise, so I forgot to add the .success(callback) in the line
$http.get('/api/propositionapi/3').success(callback);
Now everthing works.
Thanks for the hint MohammedAbbas

You could try to set the extra data as real JSON, eg:
$scope.proposition = { "marge_propose": "3" };
maybe try to console.log in your propositionRepository to view the result you're getting, place a console.log in the getProposition() as well to check if everything is passing trough fine
EDIT:
here's a working fiddle:
http://jsfiddle.net/c1zxp6uo/
bottomline: you don't call the callback, so when you do
$http.get('/api/propositionapi/3').then(function(){callback()})
it should work

Related

iron router syntax: onAfterAction

Router.route('/courses/:_catalog', function () {
var courseCatalog = this.params._catalog.toUpperCase();
Meteor.subscribe("courseCatalog", courseCatalog);
this.render('CourseDetail', {
to: 'content',
data: function () {
return Courses.findOne({catalog: courseCatalog});
}
});
}, {
onAfterAction: function() {
if (!Meteor.isClient) {
return;
}
debugger
var course = this.data(); <======
SEO.set({
title: "course.catalog"
});
}
});
In the above code, please look at the debugger statement. I want to access the data but it seems I am doing something wrong because this.data doesn't exist. I also tried Courses.find().fetch() but I only get an empty array inside onAfterAction. What's the right syntax and what am I missing?
It needs to be inside a this.ready() block:
onAfterAction: function() {
if (this.ready()) {
var course = this.data();
...
}
}
You need to subscribe to data first. Have a look at the waitOn function to do this. The server only sends the documents you subscribed to, and since you didn't subscribe, Courses.find().fetch() returns an empty array.
Also, don't put SEO stuff in onAfterAction. Put it in onRun which is guaranteed to only run once.

Exception in delivering result of invoking method

I've been testing on http calls with meteor, I used nitrous (because I had no access to my dev laptop during the weekend) and it worked fine.
But when I tried to run from my local pc it returns:
Exception in delivering result of invoking 'getMatch': TypeError:
Cannot read property 'duration' of undefined.
Any ideas of what could be the cause?
Method definition:
Dota = {};
Dota.getMatch = function() {
if (!Meteor.settings.steamToken)
throw new Meteor.Error(500, 'Enter a valid Steam Token in Meteor.settings');
var matchResponse = Meteor.http.get(
"https://api.steampowered.com/IDOTA2Match_570/GetMatchDetails/V001/?",
{
params:{
"match_id": "1305454585",
"key": Meteor.settings.steamToken
}
}
);
if (matchResponse.statusCode === 200) {
return matchResponse.data.result
}
else {
throw new Meteor.Error(500, "getMatch failed with error: "+matchResponse.statusCode);
}
}
Meteor.methods({
'getMatch': function(){
return Dota.getMatch();
}
})
Calling the method:
Meteor.call('getMatch', function(error, result){
var duration = numeral(result.duration).format('00:00:00');
Session.set('duration', duration);
var winner = Meteor.myFunctions.getWinner(result.radiant_win);
Session.set('winner', winner);
});
Template.layout.helpers({
winner: function () {
return Session.get('winner');
},
duration: function () {
return Session.get('duration');
}
});
Found a solution, I changed the location of
Meteor.methods({
'getMatch': function(){
return Dota.getMatch();
}
})
to server/server.js (I had it in packages/dota/dota.js) and now it works! Thanks #user3374348 for helping!

Subscription manager doesn't update collection after new subscription

In my Meteor application I have this situation in which I have a 'Settings' collection only on the client. So the publish function is:
Meteor.publish('settings', function (option) {
this.added("settings", "settings", {
bar: true,
foo: { .... }
});
this.ready();
});
Initially I subscribe like:
waintOn: function () {
return subs.subscribe('settings')
}
But when the route changes I subscribe again like
return subs.subscribe('settings', 10);
After this I see that the publish function runs, but on the client nothing happens.
For some reason the server thinks that the data did not change and decides to do nothing. So the question is how can I tell Meteor that the data has changed so it sends the data to the client. If the problem is completely different, I'm also very interested!!
UPDATE: the publish function might look like this:
Meteor.publish('settings', function (option) {
var list;
if (option === 10) {
list = [1,2,3,4,5];
}
this.added("settings", "settings", {
bar: true,
foo: list
});
this.ready();
});
UPDATE2: Expected solution:
var isNew = true;
Meteor.publish('settings', function () {
if(isNew) {
this.added("settings", "settings", {
bar: true,
foo: list
});
isNew = false;
}
else {
this.changed('settings', 'settings', {.....});
}
this.ready();
});
It would even be better if there was a function like this.exists('settings', 'settings') because the isNew variable feels a bit like a hack!
Anyway, I have it working now as follows:
try {
this.removed('settings', 'settings');
} catch(e){}
this.added('settings', 'settings', {...});
...

Async call generates " Error: Can't wait without a "fiber", even with _wrapAsync

I've been having a problem using an RSS parser in meteor. It's an async call, so it needs ot be wrapped, however it still doesn't seem to work. I presume this is because the anonymous on('readable' function is outside the fiber, but I can't see how to resolve it.
var FeedParser = Meteor.require('feedparser');
var request = Meteor.require('request');
function getBlog(url, parameter, id){
request(parameter)
.on('error', function (error) {
console.error(error);
})
.pipe(new FeedParser())
.on('error', function (error) {
console.error(error);
})
.on('readable', function () {
var stream = this,
item;
while (item = stream.read()) {
Items.insert(new_item);
}
});
}
var wrappedGetBlog = Meteor._wrapAsync(getBlog);
Meteor.methods({
blog: function (url, parameter, id) {
console.log('parsing blog');
var items = wrappedGetBlog(url, parameter, id);
}
});
Meteor._wrapAsync() expects the wrapped function to return error and result to a callback. Your function, getBlog(), does not do that so _wrapAsync is not the right approach.
I have wrapped that function before but used a Future.
That approach allowed me to call feedparser from a Meteor.method(), which doesn't allow async functions, but you are also trying to do an insert inside the readable event. I think that insert will complain if it is not in a fiber. Maybe like this would also be necessary:
var r = request( parameter );
r.on( 'response' , function(){
var fp = r.pipe( new FeedParser() ); //need feedparser object as variable to pass to bindEnvironment
fp.on('readable', Meteor.bindEnvironment(
function () {
var stream = this,
item;
while (item = stream.read()) {
Items.insert(new_item);
}
}
, function( error ){ console.log( error );}
, fp // variable applied as `this` inside call of first function
));
});
Fibers is another option...
var Fiber = Npm.require( "fibers" );
.on('readable', function () {
var stream = this,
item;
while (item = stream.read()) {
Fiber( function(){
Items.insert(new_item);
Fiber.yield();
}).run();
}
});

angular service and http request

creating service
myApp.factory('serviceHttp', ['$http', function(http) {
http.get($scope.url).then(function(result){
serviceVariable = result;
}
return serviceVariable;
}
Controller
function appController($scope, serviceHttp){
$scope.varX = serviceHttp;
if(serviceHttp){
// decision X;
} else {
// decision Y;
}
}
view:
input(ng-if='varX') serviceHttp Exist
input(ng-if='!varX') serviceHttp noExist
The above code always shows varX not exist because app installs during http call of service. I want to use angular service to inject variables from server to make decision at time of booting the application.
Try to rewrite factory by this way that returns promise:
myApp.factory('serviceHttp', ['$http', function(http) {
var factory = {
query: function () {
var data = http.get($scope.url).then(function(result){
return result;
},
function (result) {
alert("Error: No data returned");
});
return data;
}
}
return factory;
}]);
From controller:
serviceHttp.query().then(function (result) {
$scope.varX = = result;
}
Here is Demo Fiddle
in demo we used other URL source
If i correct understand you, you should doing it like this:
var app = angular.module('YourModule', []);
app.factory("serviceHttp", function($http) {
var serviceHttp={};
serviceHttp.yourGetRequest = function(yourUrl) {
return $http.get(yourUrl);
};
return serviceHttp;
});
And for example, controller:
var Controller = function($scope,serviceHttp) {
$scope.varX='';
$scope.loading = true;
var returnArr = serviceHttp.yourGetRequest($scope.url).success(function(dataFromServer) {
$scope.loading = false;
$scope.varX = dataFromServer;
})
};
in view you can use ng-show, like this:
<div ng-show="loading" class="loading"><img src="../styles/ajax-loader-large.gif"></div>
When your application start loading, $scope.loading = true and this div shown, and when you get response from server $scope.loading became false and div doesn't show.

Resources