Polymer data binding from Web API - html

I want to bind some data to a variable on command (by the press of a button) from a server. On the server I have a function that will return a JSON object (this has been tested, if I open the API link directly, I do get the proper JSON format). However, the variable stays undefined, no matter what I do. I have a button and a table (px-data-table is part of a framework and should be able to display JSON formatted data):
<button id="runPredictionButton">
<i>Button text</i>
</button>
<px-data-table
table-data$="{{data}}"
</px-data-table>
<div class="output"></div>
And I'm handling the button press and define the variables as follows:
<script>
Polymer({
is: 'custom-view',
properties: {
data: {
type: Object,
notify: true
}
},
ready: function() {
var self = this;
this.$.runPredictionButton.addEventListener('click', function() {
filerootdiv.querySelector('.output').innerHTML = 'Is here';
var xhr = new XMLHttpRequest();
this.data = xhr.open("GET", "API/predict") //as mentioned, API/predict returns a valid JSON
console.log("This data is:" + this.data);
this.data = xhr1.send("API/predict","_self")
console.log("This data is_:" + this.data);
});
}
});
</script>
For some reason, on the console this.data shows up as undefined both times I'm trying to print it. What am I missing? How to pass the JSON from the API call to the this.data variable?

xhr.send() doesn't return what you want.
You need to learn XmlHttpRequest first. Here is documentation. And some easy examples
Simply, you need to listen to onreadystatechange on your xml variable. There you will be able to get data from server.
Additionaly, why are you using addEventListener. You can simply set on-click.
<button id="runPredictionButton" on-click="getDataFromServer">
<i>Button text</i>
</button>
and then you can define javascript function which is called everytime user clicks on button.
getDataFromServer: function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "API/predict");
xhr.send("API/predict","_self");
xhr.onreadystatechange = function() {
// 4 = data returned
if(xhr.readyState == 4) {
// 200 = OK
if (this.xhttp.status == 200) {
// get data
this.data = xhr.responseText;
}
}
}.bind(this);
}

Related

Login Service implementation in angularjs not working

This is my controller which is calling the login service
mod.controller("loginCtrl",function($scope,loginService,$http)
{
$scope.Userlogin = function()
{
var User = {
userid :$scope.uname,
pass:$scope.pass
};
var res = UserloginService(User);
console.log(res);
alert("login_succ");
}
});
And this is the login service code which takes the User variable and checks for username & password
mod.service("loginService",function($http,$q) {
UserloginService = function(User) {
var deffered = $q.defer();
$http({
method:'POST',
url:'http://localhost:8080/WebApplication4_1/login.htm',
data:User
}).then(function(data) {
deffered.resolve(data);
}).error(function(status) {
deffered.reject({
status:status
});
});
return deffered.promise;
// var response = $http({
//
// method:"post",
// url:"http://localhost:8080/WebApplication4_1/login.htm",
// data:JSON.stringify(User),
// dataType:"json"
// });
// return "Name";
}
});
I have created a rest api using springs which upon passing json return back the username and password in json like this
Console shows me this error for angular
You need to enable CORS for your application for guidance see this link
https://htet101.wordpress.com/2014/01/22/cors-with-angularjs-and-spring-rest/
I prefer to use Factory to do what you're trying to do, which would be something like this:
MyApp.factory('MyService', ["$http", function($http) {
var urlBase = "http://localhost:3000";
return {
getRecent: function(numberOfItems) {
return $http.get(urlBase+"/things/recent?limit="+numberOfItems);
},
getSomethingElse: function(url) {
return $http.get(urlBase+"/other/things")
},
search: function (searchTerms) {
return $http.get(urlBase+"/search?q="+searchTerms);
}
}
}]);
And then in your controller you can import MyService and then use it in this way:
MyService.getRecent(10).then(function(res) {
$scope.things = res.data;
});
This is a great way to handle it, because you're putting the .then in your controller and you are able to control the state of the UI during a loading state if you'd like, like this:
// initialize the loading var, set to false
$scope.loading = false;
// create a reuseable update function, and inside use a promise for the ajax call,
// which is running inside the `Factory`
$scope.updateList = function() {
$scope.loading = true;
MyService.getRecent(10).then(function(res) {
$scope.loading = false;
$scope.things = res.data;
});
};
$scope.updateList();
The error in the console shows two issues with your code:
CORS is not enabled in your api. To fix this you need to enable CORS using Access-Control-Allow-Origin header to your rest api.
Unhandled rejection error, as the way you are handling errors with '.error()' method is deprecated.
'Promise.error()' method is deprecated according to this and this commit in Angular js github repo.
Hence you need to change the way you are handling errors as shown below :
$http().then(successCallback, errorCallback);
function successCallback (res) {
return res;
}
function errorCallback (err) {
return err;
}
One more thing in your code which can be avoided is you have defined a new promise and resolving it using $q methods, which is not required. $http itself returns a promise by default, which you need not define again inside it to use it as a Promise. You can directly use $http.then().

Angular factory does not return array of objects but a single object

I am new to angular and I am trying to load a CSV list inside a factory and then convert it to json. I am using Papaparse (CSV to json library) inside the factory. When I console log the factory I get the array of objects which is exactly what I want but when I pass it inside my controller I get a single object which holds all the data.
This is my factory
(function() {
var app = angular.module('test');
app.factory('testFactory', ['$http', function($http) {
var url = 'my-list.csv';
var getContact = function() {
return $http.get(url).success(function(data) {
Papa.parse(data, {
header: true,
complete: function(results) {
console.log(results.data);
return results.data;
}
});
});
};
return {
getContact: getContact
};
}]);
}());
And this is my controller
(function() {
var app = angular.module('test');
app.controller('testCtrl', ['$scope', 'testFactory', function($scope, testFactory) {
testFactory.getContact().then(function(data) {
$scope.contacts = data;
console.log(data);
});
}]);
}());
I want be able to do something like this inside my view
{{ contact.firstname }}
The issue is the order of resolution. Inspecting the console statements shows that you're assigning $scope.contacts to the resolution of the $http.get promise, and not the actual parsing.
Instead of returning the $http.get promise, return a deferred promise and resolve at the end of parsing:
var parsePromise = $q.defer();
$http.get(url).success(function(data) {
Papa.parse(data, {
header: true,
complete: function(results) {
console.log(results.data);
parsePromise.resolve(results.data);
}
});
});
return parsePromise.promise;
See working demo here.
Update: As per the comments, you could use .then to chain promises instead of creating a new deferred. The plunkr has both, you can use the changelog to toggle methods.

Unable to send data in response to the view in nodejs

I am trying to create a simple web application which fires a http.request call, get the data and display it over to the html(ejs here). I am able to fire the request, get the data, massage it etc.. but unable to pass it to the view. Sample code is as below:
var searchData = [];
router.post('/',requesthandler);
function requesthandler(req,res){
var options = {
host: url,
port: 9999,
path: qstring,
method: 'GET'
};
var reqget = http.request(options,responsehandler);
reqget.end();
console.log('Rendering now:............................ ');
res.render('result',{title: 'Results Returned',searchdata : searchData});
}
function responsehandler(ress) {
console.log('STATUS: ' + ress.statusCode);
ress.on('data', function (chunk) {
output += chunk;
console.log('BODY: ' );
});
/* reqget.write(output); */
ress.on('end',parseresponse);
}
function parseresponse(){
var data = JSON.parse(output);
console.log(data.responseHeader);
// populate searchData here from data object
searchData.push({//some data});
}
function errorhandler(e) {
console.error(e);
}
module.exports = router;
Problem is I a unable to pass the objeect searchData to the view via res.render();
'Rendering now: ...........' gets executed before execution starts in parseresponse() and so the page is displayed without the data which seems to be in conjuction with using callbacks, So how can I pass the data object to the view once the searchData is loaded in parseresponse().
PS: I am able to print all console statements
define res variable globally:
var res;
function requesthandler(req,resObj){
res = resObj;//set it to the resObj
}
wrap res.render inside a function like this:
function renderPage(){
res.render('result',{title: 'Results Returned',searchdata : searchData});
}
then in parseresponse function do this:
function parseresponse(){
var data = JSON.parse(output);
searchData.push({some data});
renderPage();
}
Hope this solves your problem.

Submitting Serialized JSON to a Servlet

I can successfully serialize the form and submit it to a text area in the form, but don't know how to send it to a Servlet that I have already created/defined:
// Prepare form for Serialize
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
// Send JSON Data to ResultSet
$(function() {
$('form').submit(function() {
//submitting to textarea "resultset"
//needs to submit to servlet "SftpConnTest" as defined in web.xml
//$('#ResultSet').text(JSON.stringify($('form').serializeObject()));
//?? HOW DO I SEND TO "SftpConnTest" SERVLET instead??
return false;
});
});
Use following to send form data via ajax to server:
$.post("path/to/servlet", $("#formId").serializeArray(), function (result) {
// do something
});
By the way:
serializeArray() will convert a form to an array, which could be used directly as the "data" param of a jquery ajax request, only element that has a name property in the form will be included into the data,for details please check jquery api, it's very clear there.
Assuming you are sending this to the servlet using an HTTP POST, you can use ajax:
$(function() {
$('form').submit(function(evt) {
evt.preventDefault(); // prevent the default form submit behavior
var data = $('form').serializeObject();
$.post(
'/',
data,
function(resData, status, req) {
$('#ResultSet').text(JSON.stringify(resData));
}
);
}
}
If the servlet is not mapped to be located at the root of the web app, replace 'SftpConnTest' in the $.post function with the relative path to the servlet. For example, if the servlet is mapped to /foo/bar/SftpConnTest, then you should have '/foo/bar/SftpConnTest' instead of 'SftpConnTest'.
See the jQuery docs for more information on the $.post function.

Knockout: Mapping/binding JSON

I'm new to knockout. I'm trying to bind the json returned from ajax call but it isn't happening.
<script type="text/javascript">
var ServerData;
$(document).ready(function () {
ko.setTemplateEngine(new ko.nativeTemplateEngine);
var oViewModel = new CompanyModel();
oViewModel.Newitem(new Company("","","","","","","","","","","","","","",""));
ko.applyBindings(oViewModel);
BasicDatatable('#TableCompany');
});
function CompanyModel() {
var self = this;
self.CompanyList = ko.observable();
$.getJSON("getallcompanies", function (response) {
ServerData = ko.mapping.fromJSON(response);
self.CompanyList(ServerData);
});
}
In response I've the required data. But in ServerData I'm getting the following instead of the list.
function b() { if (0 < arguments.length) { if (!b.equalityComparer || !b.equalityComparer(d, arguments[0])) b.H(), d = arguments[0], b.G(); return this } r.T.Ha(b); return d }
Can You please let me know what's going wrong?
You should use ko.mapping.fromJS to bind JSON that comes from server.
Also, you don't need to define self.CompanyList = ko.observable(); and bind set value to that property in self.CompanyList(ServerData);.
It's all done by ko.mapping.fromJS. From Knockout Mapping documentation:
All properties of an object are converted into an observable. If an
update would change the value, it will update the observable.
Arrays are converted into observable arrays. If an update would
change the number of items, it will perform the appropriate
add/remove actions. It will also try to keep the order the same as
the original JavaScript array.
Try to change code like this:
function CompanyModel() {
var self = this;
$.getJSON("getallcompanies", function (response) {
ko.mapping.fromJSON(response, {}, self);
});
}