I'm writing a search script to return a bunch of HTML, but it doesn't seem to be working, I'm trying to use $sce.
function SearchCtrl($scope, $http, $sce) {
$scope.url = 'search.php'; // The url of our search
// The function that will be executed on button click (ng-click="search()")
$scope.search = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.keywords}).success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data;
$scope.trustedExample = $sce.trustAsHtml(data);
// Show result from server in our <pre></pre> element
})
};
}
Have I done it incorrectly?
Link to the test site is here: http://elliottcoe.com/search/
Related
I have two AngularJs Controllers called "HomeController" and "VacancyController".
My HomeController have method getallData(). Below I am trying to call Homecontroller's getallData() function through ng-change event of the dropdown.
Please advise how do I call getallData() functiona as my dropdown on-change attribute is wrapped around "VacancyController"?
Below is my code:
HTML
<div ng-controller="VacancyController">
<p>Select a Vacancy:</p>
<select ng-model="selectedVacancy" ng-options="x.name for x in vacancieslist" ng-change=""></select>
<h1>Your selected Vacancy Title is : {{selectedVacancy.name}}</h1>
HomeController
.controller('HomeController', function ($scope, angularSlideOutPanel, $http, $location, $window) {
getallData();
//******=========Get All Teachers=========******
function getallData() {
$http({
method: 'GET',
url: '/Home/GetAllData'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.ListTeachers = response.data;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.errors = [];
$scope.message = 'Unexpected Error while saving data!!';
console.log($scope.message);
});
};
VacancyController
app.controller('VacancyController', ['$scope', 'VacancyService', function ($scope, VacancyService) {
$scope.GetVacancies = function () {
$scope.vacancieslist = [];
var getData = VacancyService.Vacancies();
getData.then(function (ord) {
angular.forEach(ord.data, function (val) {
if ($.trim(val).length > 0) {
var obj = new Object();
obj.name = val.VacTitle;
obj.id = val.VacNo;
if (val.VacNo > 0) {
$scope.vacancieslist.push(obj);
}
}
});
}, function () {
genericService.warningNotify("Error in getting List of Vacancies");
});
}
$scope.GetVacancies();
}]);
It is possible for one controller to call another controller, as shown in the following stack overflow(Can one controller call another?). You can use emit or broadcast depending on whether they are a child of another.
However in your case, it is better for getAllData to be placed in a service. The service would return the result of getAllData. In the service you can then either always return the result of getAllData from a http call, or cache the service (by setting it to a variable and returning it)
app.service('commonSvc', function() {
var getAllData = function{... //what you have in your code}
return {
getAllData:getAllData
}
}
By having this commonSvc, you can inject and invoke this service each time you need to call this function, similar to what you are doing for VacancyService. Keep in mind, all service in Angular are singletons. In vacancyController you can then introduce a new function onChange which calls commonSvc.getAllData.
I am working using Angular JS. I am trying to get a json object obtained using $http service to be accessible in a $scope variable. Inside all the asynchronous AJAX ($http.get()) calls, if I try to print the data obtained stored inside a $scope variable and print it, it works successfully and shows me the expected data. But outside scope of the asynchronous method, the same $scope variable assigned with data obtained loses hold of it and prints undefined.
Code:
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$http', 'getTestcaseFactory', function($scope, $routeParams, $http, getTestcaseFactory) {
$scope.myjsonobj = '';
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
console.log($scope.model); //Prints undefined
}]);
By the time
console.log($scope.model);
executes, the $http request would have not gone through yet, and this is why it prints undefined. Once the $http request is done, your $scope.model will update accordingly. You can test this by using a $timeout
$timeout(function () {
console.log($scope.model);
}, 5000);
Don't forget to inject $timeout in your controller.
This saves my day! $timeout to the rescue. Thanks #Dan Moldovan for the answer! As the $http service is asynchronous, we have to set a timer to wait for a time interval till the point the data is really received in the promise.success section and then it can be assigned to a variable inside $scope.
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$timeout', 'getTestcaseFactory', function($scope, $routeParams, $timeout, getTestcaseFactory) {
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
$timeout(function() {
console.log($scope.model); //Prints the Data now
}, 2000);
}]);
The solutions posted so far are fundemantally wrong, as they depend on an arbitrary timeout, and nothing guarantees that the async answer will be available by then.
As I suggested in a comment above, here are 2 more data/event-driven solutions.
You either only print in the callback function (which you're already doing in your example)
Or since you're using angular anyway, you can set up a watch (which in the background uses a not-too-nice dirty checking solution, but at least it's abstracted away from your code)
If you want to run a function called processData once the data is available, solution 1 you already do in your example, see this line:
console.log($scope.model);//PRINTS THE RIGHT DATA
Here you could call any other function to trigger the continuation of the process, just call whatever function:
console.log($scope.model);//PRINTS THE RIGHT DATA
processData();
Using angular's $watch mechanism (2.):
$scope.$watch(
function(){return $scope.model;},
function(newValue, oldValue){
if(newValue != null){
console.log($scope.model);
processData();
}
})
This will print the data when it is available after the async callback, and the program will continue with processing from then.
I'm trying to create a controller that gets data from Google app engine and allows me to display it on a page. The problem seems to be that the data (resp) can be accessed locally, but I can't seem to access it outside of the function. I am able to do so if I simply use javascript (...document.getElementById('getListingsResult').innerHTML = result;...), but if I invoke $scope for Angular, I can't access it any longer. Does anyone have any idea of how I can fix it while retaining the same structure to load and call gapi? Heres' my code:
(edit: added $scope.loadData, but problem persists)
phonecatControllers.controller('datastoreTestCtrl', ['$scope',
function($scope) {
$scope.data;
$scope.loadData = function() {
var ROOT = 'https://my_team.appspot.com/_ah/api';
gapi.client.load('listingserviceapi', 'v1', function(){
console.log("reached step 1");
var request = gapi.client.listingserviceapi.getListings();
request.execute(function (resp){
if (!resp.code) {
// console.debug(resp);
console.log('loaded! :)');//returns loaded
resp.items = resp.items || [];
$scope.data = resp.items;
console.log($scope.data); //returns an array of data
}
};
} , ROOT );};
$scope.loadData;
console.log($scope.data); //returns [object, object] which is incorrect
}]);
It should work using promise. Also, there is a missing parenthesis for request.execute function in your code.
Check the below code (untested):
phonecatControllers.controller('datastoreTestCtrl', ['$scope', '$q',
function ($scope, $q) {
$scope.data = null;
$scope.loadData = function () {
var deferred = $q.defer(),
ROOT = 'https://my_team.appspot.com/_ah/api';
gapi.client.load('listingserviceapi', 'v1', function () {
console.log("reached step 1");
var request = gapi.client.listingserviceapi.getListings();
request.execute(function (resp) {
if (!resp.code) {
// console.debug(resp);
console.log('loaded! :)'); //returns loaded
resp.items = resp.items || [];
//$scope.data = resp.items;
//console.log($scope.data); //returns an array of data
deferred.resolve(resp.items);
}
}); //---missing parenthesis here
}, ROOT);
return deferred.promise;
};
$scope.loadData().then(function (data) {
$scope.data = data;
console.log($scope.data); //returns [object, object] which is incorrect
});
}]);
That is because you are doing asynchronous call. When you trying to access $scope.data from outside of your callback your request is not finished yet it is still in process. You have to make sure that your request is done.
I'm new to AngularJS and am still trying to wrap my head around using services to pull data into my application.
I am looking for a way to cache the result of a $http.get() which will be a JSON array. In this case, it is a static list of events:
[{ id: 1, name: "First Event"}, { id: 2, name: "Second Event"},...]
I have a service that I am trying to use to cache these results:
appServices.service("eventListService", function($http) {
var eventListCache;
this.get = function (ignoreCache) {
if (ignoreCache || !eventListCache) {
eventListCache = $http.get("/events.json", {cache: true});
}
return eventListCache;
}
});
Now from what I can understand I am returning a "promise" from the $http.get function, which in my controller I add in a success callback:
appControllers.controller("EventListCtrl", ["$scope", "eventListService",
function ($scope, eventListService) {
eventListService.get().success(function (data) { $scope.events = data; });
}
]);
This is working fine for me. What I'd like to do is add an event to the eventListService to pull out a specific event object from eventListCache.
appServices.service("eventListService", function($http) {
var eventListCache;
this.get = function (ignoreCache) { ... }
//added
this.getEvent = function (id) {
//TODO: add some sort of call to this.get() in order to make sure the
//eventListCache is there... stumped
}
});
I do not know if this is the best way to approach caching or if this is a stupid thing to do, but I am trying to get a single object from an array that may or may not be cached. OR maybe I'm supposed to call the original event and pull the object out of the resulting array in the controller.
You're on the right track. Services in Angularjs are singeltons, so using it to cache your $http request is fine. If you want to expose several functions in your service I would do something like this. I used the $q promise/deferred service implementation in Angularjs to handle the asynchronus http request.
appServices.service("eventListService", function($http, $q) {
var eventListCache;
var get = function (callback) {
$http({method: "GET", url: "/events.json"}).
success(function(data, status) {
eventListCache = data;
return callback(eventListCache);
}).
}
}
return {
getEventList : function(callback) {
if(eventListCache.length > 0) {
return callback(eventListCache);
} else {
var deferred = $q.defer();
get(function(data) {
deferred.resolve(data);
}
deferred.promise.then(function(res) {
return callback(res);
});
}
},
getSpecificEvent: function(id, callback) {
// Same as in getEventList(), but with a filter or sorting of the array
// ...
// return callback(....);
}
}
});
Now, in your controller, all you have to do is this;
appControllers.controller("EventListCtrl", ["$scope", "eventListService",
function ($scope, eventListService) {
// First time your controller runs, it will send http-request, second time it
// will use the cached variable
eventListService.getEventList(function(eventlist) {
$scope.myEventList = eventlist;
});
eventListService.getSpecificEvent($scope.someEventID, function(event) {
// This one is cached, and fetched from local variable in service
$scope.mySpecificEvent = event;
});
}
]);
You are on the right track. Here's a little help:
appServices.service("eventListService", function($http, $q) {
var eventListCache = [];
function getList(forceReload) {
var defObj = $q.defer(), listHolder;
if (eventListCache.length || forceReload) {
listHolder= $http.get("/events.json", {cache: true});
listHolder.then(function(data){
eventListCache = data;
defObj.resolve(eventListCache);
});
} else {
defObj.resolve(eventListCache);
}
return defObj.promise;
}
function getDetails(eventId){
var defObj = $q.defer();
if(eventId === undefined){
throw new Error('Event Id is Required.');
}
if(eventListCache.length === 0){
defObj.reject('No Events Loaded.');
} else {
defObj.resolve(eventListCache[eventId]);
}
return defObj.promise;
}
return {
eventList:getList,
eventDetails:getDetails
};
});
Then, in your controller, you handle it like this:
appControllers.controller("EventListCtrl", ["$scope", "eventListService",
function ($scope, eventListService) {
var eventList = eventListService.getList();
eventList.then(function(data){
$scope.events = data;
});
$scope.getEventsList = function(reloadList){
eventList = eventListService.getList(reloadList);
eventList.then(function(data){
$scope.events = data;
});
};
$scope.getEventDetails = function(eventID){
var detailsPromise = eventListService.getDetails(eventID);
detailsPromise.then(function(data){
$scope.eventDetails = data;
}, function(reason){
window.alert(reason);
});
}
}
]);
This way, your events are loaded when the controller first loads, and then you have the option to request a new list by simply passing in a boolean. Getting event details is also handled by an internal promise to give you some error handling without throwing a disruptive error.
I want bind the values from WCF service to controller. but am not able to bind the values from WCF result. but if i use online webservice means its working perfectly.
please help me. i wasted lots of time. i share the code and screen which is worked.
This is My HTML Code.
<div ng-controller = "fessCntrl">
<ul><li ng-click="alertSwap()">click </li></ul>
<ul><pre>data {{data|json}}</pre></ul>
</div>
This is my Angular JS Code
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function ($scope, stockData) {
$scope.alertSwap = function () {
stockData.query('somedata')
.then(function (result) {
$scope.data = result.data;
}, function (result) {
alert("Error: No data returned");
});
}
});
fessmodule.$inject = ['$scope', 'Data'];
fessmodule.factory('stockData', ['$http', '$q', function ($http, $q) {
var factory = {
query: function (value) {
// here you can play with 'value'
var data = $http.get('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22YHOO%22)%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json');
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
}]);
This is perfectly working Online webservice.
This my webservice which is not working my WCF Service.
try this
query: function (value) {
// here you can play with 'value'
var data =[];
**$http.get('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22YHOO%22)%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json').success(response)
{
data = response;//Or value=response.Data;
};**
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
Instead of your's ..