Parameter is not recognised by the function in .then angularjs - javascript

What I am trying to achieve is a dropdown list that produces lisof Metacategories. Once the user selects the meta category, the parameter should be passed onto the URI of the function present in $scope.meta().then(...). however, the parameter I am passing is category; ng-model="category". This parameter is not sent to the URI, I am getting an error:
TypeError: Cannot read property 'category' of undefined
HTML:
</select></center >
<center> <select ng-model="category" > <!-- This produces drop down list from which the users selects a category which should then get passed to the meta1() function as a parameter to produce a further list for the drop down after that-->
<option size=50 value="" selected>Select a meta category</option>
<option ng-repeat="meta in metas.metas" value="{{meta}}">{{meta}} </option>
</select></center>
<center> <select ng-model="category" >
<option size=50 value="" disabled selected>Select a category</option>
<option ng-repeat="category in categories.categories" value="{{category}}">{{category}} </option>
</select></center>
Angular:
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/post', {
templateUrl: 'templates/post.html',
controller: 'PostCtrl'
})
}])
.controller('UserListCtrl', function ($scope, $http) {
$scope.list = function () { // this gets the list of places which works completely fine.
$http.get('http://94.125.132.253:8001/getuncategorisedplaces').success(function (data) {
$scope.places = data;
console.log(data);
$scope.message = 'List of Uncategorised places';
$scope.meta = function () { // this gets list of meta categories, which is working fine.
return $http.get('http://94.125.132.253:8000/getmetas').success(function (data) {
$scope.metas = data;
console.log(data);
$scope.message = 'List of Uncategorised places';
})
}
// the function below should get a parameter category from previous function which is selected in HTML. Once this happens, the parameter category should be passed on as formdata.category(below) which will get the list of categories.
$scope.meta().then(function (data) {
var formdata = {
'category': this.category,
}
var inserturl = 'http://94.125.132.253:8000/getcategories?meta=' + formdata.category;
$http.get(inserturl).success(function (data) {
$scope.categories = data;
console.log(formdata.category);
console.log(data);
$scope.message = 'List of Uncategorised places';
});
});
})
}
$scope.list();

I would think that the error is caused by this:
$scope.meta().then(function meta1($scope,$http) {
because the meta method is not returning a promise.
The meta method could return a promise if you did this:
$scope.meta= function(){
return $http.get('http://94.125.132.253:8000/getmetas').success(function (data) {
$scope.metas = data;
console.log(data);
$scope.message = 'List of Uncategorised places';
return data;
});
};
and you could change the call to meta to this
$scope.meta().then(function(data) {
...
}

Missing return.
$scope.meta should return a promise for you to be able to use .then()
$scope.meta= function(){
return $http.get('http://94.125.132.253:8000/getmetas').success(function(...
...
}
$scope.meta().then(function (data) {
// do something with data
});

Related

ng-model for select with defined options

I've got a plain select control in my angular app. When page loads I've got no element selected in select control but if I check $scope.data.Method I've got a correct value in int. Is there any way to fix this issue?
<div class="form-group">
<label class="col-sm-3 control-label">Selected Method:</label>
<div class="col-sm-4">
<select class="form-control" ng-model="data.Method">
<option value="0">Auction</option>
<option value="1">Delivery</option>
<option value="2">Range Delivery</option>
<option value="3">Broadcast</option>
<option value="4">Self broadcast</option>
<option value="5">Manual</option>
<option value="6">Automated</option>
</select>
</div>
</div>
Controlers use service to get data. Here is service code for getting data
//Initialize Resource
this.initResource = function (params) {
params = params || {};
params.id = '#id';
this.resource = $resource('{0}/:id'.format(this.api), params, {
'update': { method: 'POST' },
'create': { method: 'PUT' },
'default': { method: 'GET', params: { id: 'default' } }
});
}
//...more code
//Get some data and initialize additional parameters
this.read = function (id, clone, readonly, version) {
if (clone == undefined)
clone = false;
if (readonly == undefined)
readonly = false;
if (this.resource == null) {
this.initResourceByDefault();
}
return this.resource.get({ id: id, clone: clone, readonly: readonly, version: version });
}
Controller code
function ItemController($scope, $route, $routeParams, $location, $resource, MainCRUDService, ControllerHelper) {
$scope.noticeType = $routeParams.noticeType;
MainCRUDService.initResource({ noticeType: $scope.noticeType });
//Here I am getting data from resourse via service
ControllerHelper.initCRUD($scope, MainCRUDService);
}
As I can understand your problem, your service is returning data.Method as an integer value.
But select box will match a string value.
Your problem will get solved if your service will return data.Method as string. Also you can convert your response paramter data.Method to a string value, by using toString() method.
Here is a plunker code which may help you.
https://plnkr.co/edit/s0Wrk4?p=preview

AngularJs json URL changer

I'm working on some mega simple weather app in Angular for practice reasons and i'm stuck..
i have a angular json feed like this:
app.factory('forecast', ['$http', function($http) {
return $http.get('http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,NL&lang=NL_nl&units=metric')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
and it loads the feed in to the index.html. its all working and what i wand now is a input form on index that changes the Amsterdam part of the url on js/services/forcast.js where the above code is to another city so people can see their city weather.
See the demo here: http://dev.bigstoef.nl/workspace/shiva/weer/index.html
Ive tryd about all posable options about now and i'm 3 days further and its a no go. What is there correct way here?
First, create a "configurable" service :
app.factory('forecast', ['$http', function($http) {
var city;
var cities = {
amsterdam: 'Amsterdam,NL',
paris: 'Paris,FR'
};
var api_base_url = 'http://api.openweathermap.org/data/2.5/weather';
var other_params = 'lang=NL_nl&units=metric';
return {
setCity: function(cityName){
city = cityName ;
console.log(city);
},
getWeather: function(cityName){
console.log(city);
if(cityName) this.setCity(cityName);
if (!city) throw new Error('City is not defined');
return $http.get(getURI());
}
}
function getURI(){
return api_base_url + '?' + cities[city] + '&' + other_params;
}
}]);
Then you can create a controller like the following:
app.controller('forecastCtrl', ['$scope', 'forecast',function($scope,forecast){
$scope.city = 'amsterdam' ;
$scope.$watch('city',function(){
console.log($scope.city);
forecast.setCity($scope.city);
});
$scope.getWeather = function(){
console.log('get weather');
forecast.getWeather()
.success(function(data){
console.log('success',data);
$scope.weatherData = data;
}).error(function(err){
console.log('error',err);
$scope.weatherError = err;
});
};
}]);
To implement a template as the following
<link rel="stylesheet" href="style.css" />
<div data-ng-controller="forecastCtrl">
<form>
<label>
<input type="radio" name="city" data-ng-model="city" data-ng-value="'amsterdam'">Amsterdam
</label>
<br/>
<label>
<input type="radio" name="city" data-ng-model="city" data-ng-value="'paris'">Paris
</label>
<br/>
<button data-ng-click="getWeather()">Get Weather</button>
</form>
<p class="weather-data">
{{weatherData}}
</p>
<p class="weather-error">
{{weatherError}}
</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="script.js"></script>
You can view the code working here : http://plnkr.co/edit/rN14M8GGX62J8JDUIOl8?p=preview
You can return a function in your factory. Define your forcast as
app.factory('forecast', ['$http', function($http) {
return {
query: function(city) {
return $http.get('http://api.openweathermap.org/data/2.5/weather?q=' + city + '&lang=NL_nl&units=metric')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}
};
}]);
Then in your controller
forecast.query('Amsterdam,NL').success(function(data) {
$scope.weer = data;
});
Change service code to have a dedicated method which you can call multiple times with different parameters (cities):
app.factory('forecast', ['$http', function($http) {
return {
load: function(location) {
return $http.get('http://api.openweathermap.org/data/2.5/weather?q=' + location + '&lang=NL_nl&units=metric')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}
}
}]);
Then in controller you would be able to load forecat for other locations when you need:
forecast.load('Amsterdam,NL').then(function(data) {
$scope. weer = data;
});
Demo: http://plnkr.co/edit/GCx35VxRoko314jJ3M7r?p=preview

Drop down not getting displayed

Problem Question -
I have a two drop down in my view. And second drop down rely on the first one. But somehow second one does not get updated
// my firstdrop down
<select ng-controller="myController"
ng-options="customer.name for customer in customerDetailData" ng-model="customer"
ng-change="updateCost(customer)">
<option value="">Please select customer</option>
</select>
// my second drop down
<select ng-controller="myController"
ng-options="cc.name for cc in customerCostData">
<option value="">Please select cost</option>
</select>
// my controller
(function() {
var myController = function($scope,Service){
$scope.customerDetailData;
Service.cust()
.success(function(data){
console.log(data)
$scope.customerDetailData = data;
})
.error(function(status,error){
})
$scope.customerCostData;
$scope.updateCost=function(customer){
Service.cost(customer.id)
.success(function(cost){
$scope.customerCostData= cost
})
.error(function(status,data){
console.log(status);
console.log(data);
})
}
};
myController .$inject = ['$scope','Service'];
angular.module('app').controller('myController ',myController );
}());
Is anything i am missing ? the data is coming through fine in the console. Please guide me
There are 2 things to do here:
The first and main issue is that you are attaching ng-controller to each select individually. This means it is actually creating 2 separate controllers, one for each select, and so they are given different scopes. You need to apply the ng-controller attribute to a parent element, such as the form.
The second issue is that angular will not automatically update an element just because the scope variable is used in ng-options. You therefore need to give it a ng-model so that Angular watches it correctly.
Here is an example of the code with two separate controller instances. Note the 2 alerts:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<form ng-app="myApp">
<select ng-controller="myController"
ng-options="customer.name for customer in customerDetailData" ng-model="customer"
ng-change="updateCost(customer)">
<option value="">Please select customer</option>
</select>
<select ng-controller="myController"
ng-options="cc.name for cc in customerCostData" ng-model="customercustomerCostData">
<option value="">Please select cost</option>
</select>
</form>
<script type="text/javascript">
(function () {
var myApp = angular.module('myApp', []);
var myController = function ($scope) {
alert('myController created');
$scope.customerDetailData = [{ id: 1, name: "bob" }, { id: 2, name: "fred" }];
$scope.updateCost = function (customer) {
$scope.customerCostData = [{ name: customer.id.toString() }, { name: 'x' }];
}
};
myController.$inject = ['$scope'];
myApp.controller('myController', myController);
}());
</script>
Here it is with the single ng-controller applied to the form and ng-model="customerCostData" on the second select, so it now works:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<form ng-app="myApp" ng-controller="myController">
<select
ng-options="customer.name for customer in customerDetailData" ng-model="customer"
ng-change="updateCost(customer)">
<option value="">Please select customer</option>
</select>
<select
ng-options="cc.name for cc in customerCostData" ng-model="customercustomerCostData">
<option value="">Please select cost</option>
</select>
</form>
<script type="text/javascript">
(function () {
var myApp = angular.module('myApp', []);
var myController = function ($scope) {
alert('myController created');
$scope.customerDetailData = [{ id: 1, name: "bob" }, { id: 2, name: "fred" }];
$scope.updateCost = function (customer) {
// would be an ajax call
$scope.customerCostData = [{ name: customer.id.toString() }, { name: 'x' }];
}
};
myController.$inject = ['$scope'];
myApp.controller('myController', myController);
}());
</script>
is the cost data the result of an Ajax request? if so, you may need to force a force a $digest cycle to let the UI know the model has been changed. You can achieve this by wrapping the assignment of cost in a $timeout, or $apply.
$timeout(function () {
$scope.customerCostData = cost;
});
or
$scope.$apply(function () {
$scope.customerCostData = cost;
});

How to write an angularJs Controller to GET Rest Data from Parse.com

See solution below:
I'm trying to connect to a Parse.com Rest backend and display data from object values.
HTML (I put several angular calls to be sure to catch output):
<div ng-controller="MyController">
<p>{{item}}<p>
<p>{{items}}<p>
<p>{{item.firstName}}<p>
<p>{{data}}<p>
</div>
JAVASCRIPT rest:
function MyController($scope, $http) {
$scope.items = [];
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Professional/id', headers: { 'X-Parse-Application-Id':'XXXX', 'X-Parse-REST-API-Key':'YYYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
});
};
}
This won't work, it does strictly nothing, not even a message in the console.
I know the rest call got the correct credential, as I'm able to get object content returned when I test it with a rest tester program. Maybe the URL should not be absolute ?
Any clue is very welcome, i've spent DAYS on that.
SOLUTION:
Thanks to the help of people answering this thread, I was able to find the solution to this problem so I just wanted to contribute back:
Get Json object data from Parse.com backend, pass it authentification parameters:
function MyController($scope, $http) {
$scope.items = [];
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Professional', headers: { 'X-Parse-Application-Id':'XXX', 'X-Parse-REST-API-Key':'YYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
});
};
Notice that ' ' necessary arround header key object values. Those ' ' are not necessary around method and url keys.
Template that list all 'firstName' of each object:
<div ng-controller="MyController" ng-init="getItems()">
<ul>
<li ng-repeat="item in items.results"> {{item.firstName}} </li>
</ul>
</div>
Notice: "item in items.results". "results" is necessary because the return value is a JSON object that contains a results field with a JSON array that lists the objects. This could save you some headache.
Also notice "ng-init": if you don't put that, or any other form of call to the getItem(),then nothing will happen and you will be returned no error.
That was my first try of Angularjs, and i'm already in love ^^.
Based in your request the controller should be:
HTML
<div ng-controller="MyController">
<button type="button" ng-click="getItems()">Get Items</button>
<ul>
<li ng-repeat="item in items"> item.firstName </li>
</ul>
</div>
JS
function MyController($scope, $http) {
$scope.items = []
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Users', headers: { 'X-Parse-Application-Id':'XXXXXXXXXXXXX', 'X-Parse-REST-API-Key':'YYYYYYYYYYYYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
})
}
}
Just a little update to the newer versions of Angular (using .then since version 1.5):
myApp.controller('MyController', function($scope, $http) {
$scope.items = []
$http({
method: 'GET',
url: 'https://api.parse.com/1/classes/Users',
headers: {'X-Parse-Application-Id':'XXXXXXXXXXXXX', 'X-Parse-REST-API-Key':'YYYYYYYYYYYYY'}
})
.then(function successCallback(response) {
alert("Succesfully connected to the API");
$scope.items = data;
}, function errorCallback(response) {
alert("Error connecting to API");
});
});
var app = angular.module("app",[]);
app.controller("postcontroller", function($scope, $http){
$scope.getAllProjects = function() {
var url = 'https://reqres.in/api/products';
$http.get(url).then(
function(response) {
$scope.projects = response.data.data;
},
function error(response) {
$scope.postResultMessage = "Error with status: "
+ response.statusText;
});
}
$scope.getAllProjects();
});
<div ng-app="app">
<div ng-controller="postcontroller">
<div class="panel-body">
<div class="form-group">
<label class="control-label col-sm-2" for="project">Project:</label>
<div class="col-sm-5">
<select id="projectSelector" class="form-control">
<option id="id" ng-repeat="project in projects"
value="{{project.id}}">{{project.name}}</option>
</select>
</div>
</div>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>

AngularJS model is populated in javascript but empty on the page

I've got this code...
Agencyapp.factory('AgencyData', function ($http, $log) {
return {
getAgencies: function(successcb){
$http({ method: 'GET', url: 'http://localhost/MappingServicesWebAPI/api/mapping' }).
success(function(data){
successcb(data);
}).
error(function(data){
$log.warn(data, status, headers, config);
})
}
}
});
Which gets data from a WebAPI. The $scope.Agencies model gets populated with an AgencyList array. When I try to use that array...
<div ng-controller="AgenciesCtrl">
<select ng-model="Agencies">
<option>Select Agency</option>
<option ng-repeat="A in Agencies" >{{A.AgencyList.AgencyName}}</option>
</select>
{{Agencies.AgencyList}}
</div>
It's empty...can someone help me with what I might be doing wrong?
Here's the controller, sorry I thought I included it...
Agencyapp.controller('AgenciesCtrl', function AgenciesCtrl($scope, AgencyData) {
AgencyData.getAgencies().then(function (rtnAgencies) {
$scope.Agencies = rtnAgencies;
});
});
I tried to post a picture of the populated $scope object but I don't have enough reputation points...
It Looks like this(each indent is a nested object)...
$scope.Agencies
[prototype]
AgencyList[]
[0]
[prototype]
AgencyID -10168
AgencyName "#1 Insurance Agency"
If I hard code data...
function AgenciesCtrl($scope, AgencyData) {
$scope.Agencies = [
{
AgencyID: 'Test One',
AgencyName: 'Agency Test 1'
},
{
AgencyID: 'Test Two',
AgencyName: 'Agency Test 2'
}];
};
It Works
If I hard code data inside the function call
function AgenciesCtrl($scope, AgencyData) {
AgencyData.getAgencies().then(function (rtnAgencies) {
$scope.Agencies = [
{
AgencyID: 'Test One',
AgencyName: 'Agency Test 1'
},
{
AgencyID: 'Test Two',
AgencyName: 'Agency Test 2'
}];
});
};
It doesn't work
I haven't seen one good example of using data from a web api...all examples I have seen hard code data, what's the point in that?
First, remove ng-model="Agencies" from your <select> element. You dont want to bind your select element to the same object that you are running an ng-repeat on. Try something like <select ng-model="selectedAgency" > instead.
Second, I suggest utilizing angular's deferred API to return a promise, which will then be resolved with the value of the data returned from the server, when it is finished:
Agencyapp.factory('AgencyData', function ($http, $log, $q) {
return {
getAgencies: function(successcb){
var deferred = $q.defer();
$http({ method: 'GET', url: 'http://localhost/MappingServicesWebAPI/api/mapping' }).
success(function(data){
deferred.resolve(successcb(data)); //I dont know what successcb() does
}).
error(function(data){
deferred.reject(data);
$log.warn(data, status, headers, config);
})
return deferred.promise;
}
};
});
In your controller, you would then do something like this:
AgencyData.getAgencies().then(function(data) {
$scope.Agencies = data;
});
As soon as the getAgencies() function finishes getting the data, the $scope.Agencies object will be updated with the resulting data.
It turns out I had my...
<div ng-controller="AgenciesCtrl">
<select ng-model="Agencies">
<option>Select Agency</option>
<option ng-repeat="A in Agencies" >{{A.AgencyList.AgencyName}}</option>
</select>
{{Agencies.AgencyList}}
</div>
Inside a that was controlled by a Javascript Library called Slidebox.js.
Once I removed Slidebox.js everything worked correctly.

Categories