ionic: I have a scope variable empty from a stringified json - json

I'm trying to filter a JSON result from a SQLite query. The filter works when I use JSON directly, but it doesn't when I use the query from the service. Then, the $scope.arrayme just appears as empty.
Where is the error? Thank you!
This is the service:
getSubtipos: function() {
var query = "SELECT subtipos.idsubtipo, subtipos.tipos_idtipo, subtipos.nombre, subtipos.icon, subtipos.val FROM subtipos";
var arraySubtipos = [];
$cordovaSQLite.execute(db, query, []).then(function(res) {
if(res.rows.length > 0) {
for(var i = 0; i < res.rows.length; i++) {
arraySubtipos.push(res.rows.item(i));
}
} else {
console.log("No results found");
}
}, function (err) {
console.error("ERROR: " + err.message);
}).finally(function() {
arraySubtipos = JSON.stringify(arraySubtipos);
});
return arraySubtipos;
}
This is the controller:
.controller('MenuSubtiposCtrl', function($scope, $filter, miJson, $stateParams, $cordovaSQLite){
var arrayme = JSON.stringify(miJson.getSubtipos());
$scope.arrayme = $filter("filter")(JSON.parse(arrayme), {tipos_idtipo: $stateParams.foo});
})
And this is the state:
.state('app.menusubtipos', {
url: "/menusubtipos/:foo",
views: {
'menuContent': {
templateUrl: "templates/menuSubtipos.html",
controller: "MenuSubtiposCtrl"
}
}
})

There may be more problems than what I've immediately noticed, but I have have noticed that you're returning a variable within your getSubtipos function before it's set.
The $cordovaSQL.execute() function is an asyncronous function. As a result, you are returning arraySubtipos before it's set.
A better way to do this would be within getSubtipos to do the following:
var arraySubtipos = [];
return $q.when($cordovaSQLite.execute(db, query, [])
.then(function(res) {
if(res.rows.length > 0) {
for(var i = 0; i < res.rows.length; i++) {
arraySubtipos.push(res.rows.item(i));
}
} else {
console.log("No results found");
}
return JSON.stringify(arraySubtipos);
}));
// Then, within your controller, do the following:
.controller('MenuSubtiposCtrl', function($scope, $filter, miJson, $stateParams, $cordovaSQLite){
miJson.getSubtipos()
.then(function(arrayMe) {
// No need to stringify it again
$scope.arrayme = $filter("filter")(JSON.parse(arrayme), {tipos_idtipo: $stateParams.foo});
})
.catch(function(error) {
// Handle the error here
});
var arrayme = JSON.stringify(miJson.getSubtipos());
});
I'm also a little suspicious about your use of JSON.stringify and JSON.parse. It's likely that they're not needed, but without knowing the format of your data, I've left that as is.

Related

How to convert numbers to hexadecimal value in AngularJS. And the numbers will be taken from user.

i tried this
//Body
<input type="number" ng-model="show">
<h2>{{show}}</h2>
//Controlelr
a.controller("cont", function($scope, convertr){
$scope.show = convertr.myFunc(show);
});
//Custom Service
a.service("convertr", function(){
this.myFunc = function(){
return x.toString(16)
};
});
Sorry I am new in angularjs and i am new in Stackoverflow. So dont know much about how to do things. Please help me with this problem.
You declare a service as a factory, and this factory must return whatever you need to expose from that service :
a.factory("convertr", function() {
return {
myFunc: function(x) {
return x.toString(16)
}
}
});
You van have local variable and functions in the service
a.factory("convertr", function() {
var localVariable = 42;
function doSomething() {
}
return {
myFunc: function(x) {
return x.toString(16)
}
}
});
You can inject other services by adding the service names as parameter to the service function a.factory("convertr", function($http) { (implicit, not recommended) or preferred with inline array annotation
a.factory("convertr", ['$http', function($http) {
return {
myFunc: function(x) {
return x.toString(16)
}
}
}]);
You can use simple scope-wrapping to call toString of number
function hexSample() {
let number = prompt("enter your number", "");
if (number != null) {
document.getElementById("result").innerHTML =
"Heximal number of " + number + " : " + (Number(number)).toString(16);
}
}
<button onclick="hexSample()">Try it</button>
<p id="result"></p>

How can I do http request in Angular, and have functions that returns all elements of Json or just one?

I'm new in Angular and Ionic,
and I want to build one factory that gets one Json from googleapis,
and contains two functions, one returns all the elements, and another that returns the element passing index in parameter.
I'm trying in this way:
Factory:
angular.module('starter.services', [])
.factory('Noticias', function($http,$q) {
var deferred = $q.defer();
$http.get("http://ajax.googleapis.com/ajax/services/feed/load", { params: { "v": "1.0", "q": "http://www.furg.br/bin/rss/noticias.php", "num":"10" } })
.success(function(data) {
entries = data.responseData.feed.entries;
deferred.resolve(entries);
})
.error(function(data) {
console.log("ERROR: " + data);
});
var noticias = deferred.promise;
console.log(noticias);
return {
all: function() {
return noticias;
},
remove: function(noticia) {
noticias.splice(noticias.indexOf(noticia), 1);
},
get: function(noticiaId) {
for (var i = 0; i < noticias.length; i++) {
if (noticias[i].id === parseInt(noticiaId)) {
return noticias[i];
}
}
return null;
}
};
});
I got this in console, but I want the just the "value" at controller.
Promise {$$state: Object, then: function, catch: function, finally: function}$$state: Object
status: 1
value: Array[10]
0: Object
1: Object
2: Object
3: Object
4: Object
5: Object
6: Object
7: Object
8: Object
9: Object
length: 10
__proto__: Array[0]
__proto__: Object
__proto__: Object
noticias is a promise. And all your methods use it as if it was an array. It's not. It's a promise.
So, the method get for example should be
get: function(noticiaId) {
return noticias.then(function(array) {
for (var i = 0; i < array.length; i++) {
if (array[i].id === parseInt(noticiaId)) {
return array[i];
}
}
return null;
});
}
and the user of the get() method should use it like this:
service.get(i).then(function(element) {
// do something with element
});
Also note that your way of defining the promise is an antipattern. If the http request fails, the noticias promise is never rejected. Use promise chaining:
var noticias = $http.get("http://ajax.googleapis.com/ajax/services/feed/load", { params: { "v": "1.0", "q": "http://www.furg.br/bin/rss/noticias.php", "num":"10" } })
.then(function(response) {
return response.data.responseData.feed.entries;
});
I believe you want to do this:
app.factory('Noticias', function($http, $q) {
var http_get_success_callback = function(data) {
var entries = data.responseData.feed.entries;
return entries;
};
var jsonData = $q.when($http.get("http://ajax.googleapis.com/ajax/services/feed/load", { params: { "v": "1.0", "q": "http://www.furg.br/bin/rss/noticias.php", "num":"10" } }).then(http_get_success_callback));
this.getAllNoticias = function() {
return jsonData;
}
this.getIndexNoticia = function(index) {
return jsonData[index];
}
});
My solution :
Based on: https://stackoverflow.com/a/33023283/5424391
angular.module('starter.services', [])
.factory('Noticias', function($http,$q) {
var noticias = $http.get("http://ajax.googleapis.com/ajax/services/feed/load", { params: { "v": "1.0", "q": "http://www.furg.br/bin/rss/noticias.php", "num":"20" } })
.then(function(response) {
return response.data.responseData.feed.entries;
});
return {
all: function() {
return noticias.then(function(array){
return array;
});
},
get: function(noticiaIndex) {
return noticias.then(function(array) {
return array[parseInt(noticiaIndex)];
});
}
};
});

Setting data in viewModel knockoutjs from html5 websocket

I am trying to create knockout.js component that is getting data from HTML5 Websocket. Websocket code is in separate script e.g. util.js. I am able to connect and get data from socket, but dont know how correctly to set corresponding property in component`s ViewModel.
Websocket - util.js:
var options = {
server: '127.0.0.1',
port: '12345'
};
var socket, loadedFlag;
var timeout = 2000;
var clearTimer = -1;
var data = {};
function handleErrors(sError, sURL, iLine)
{
return true;
};
function getSocketState()
{
return (socket != null) ? socket.readyState : 0;
}
function onMessage(e)
{
data=$.parseJSON(e.data);
// ???? Is it possible to have here something like
// ???? viewModel.getDataWS1(data);
}
function onError()
{
clearInterval(clearTimer);
socket.onclose = function () {
loadedFlag = false;
};
clearTimer = setInterval("connectWebSocket()", timeout);
}
function onClose()
{
loadedFlag = false;
clearInterval(clearTimer);
clearTimer = setInterval("connectWebSocket()", timeout);
}
function onOpen()
{
clearInterval(clearTimer);
console.log("open" + getSocketState());
}
function connectWebSocket()
{
if ("WebSocket" in window)
{
if (getSocketState() === 1)
{
socket.onopen = onOpen;
clearInterval(clearTimer);
console.log(getSocketState());
}
else
{
try
{
host = "ws://" + options.server + ":" + options.port;
socket = new WebSocket(host);
socket.onopen = onOpen;
socket.onmessage = function (e) {
onMessage(e);
};
socket.onerror = onError;
socket.onclose = onClose;
}
catch (exeption)
{
console.log(exeption);
}
}
}
}
Component (productDisplay.js) - creating so that is can be used on multiple pages:
define([
'jquery',
'app/models/productDisplayModel',
'knockout',
'mapping',
'socket'
],
function ($, model, ko, mapping) {
ko.components.register('product', {
viewModel: {require: 'app/models/productModel'},
template: {require: 'text!app/views/product.html'}
});
});
Product ViewModel (productModel.js) - where I struggle to set viewModel property to data from websocket:
var viewModel = {};
define(['knockout', 'mapping', 'jquery'], function (ko, mapping, $) {
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = ko.observableArray(); // Start empty
}
MyViewModel.prototype.getDataWS1 = function () {
//Websocket has not connected and returned data yet, so data object is empty
// ???? Is there anyway I can add something like promise so that the value is set once socket is connected?
this.products(data);
};
// apply binding on page load
$(document).ready(function () {
connectToServer1();
viewModel = new MyViewModel();
ko.applyBindings(viewModel);
viewModel.getDataWS1();
});
});
Thank you for any ideas.
You can update an observable when you get a message in the following manner:
util.js
function onMessage(e) {
var productData = $.parseJSON(e.data);
viewModel.addNewProduct(productData);
}
productModel.js
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = ko.observableArray(); // Start empty
}
MyViewModel.prototype.addNewProduct(product) {
var newProduct = new Product(product.name, product.rating);
this.products.push(newProduct);
}
Basically the idea is that when you get a message (in onMessage function), you will parse the data and call a function in your viewmodel to add the message data to the viewmodel properties (observables, observableArrays, etc.)

AngularJS + Parse REST API - Paging through more than 1,000 results

Im using Parse REST API + AngularJS and Im trying to be able to get more than 1000 items per query. I try to develop a recursive function and concatenate each query until I get all the data. My problem is that I am not able to concatenate the JSON objects successfully. Here is what I have:
$scope.getAllItems = function(queryLimit, querySkip, query) {
$http({method : 'GET',
url : 'https://api.parse.com/1/classes/myClass',
headers: { 'X-Parse-Application-Id':'XXX','X-Parse-REST-API-Key':'YYY'},
params: {limit:queryLimit, skip:querySkip},
}).success(function(data, status) {
query.concat(data.results);
if(query.lenth == queryLimit) {
querySkip += queryLimit;
queryLimit += 100;
$scope.getAllItems(queryLimit, querySkip, query);
} else {
$scope.clients = query;
}
})
.error(function(data, status) {
alert("Error");
});
};
var myQuery = angular.toJson([]); //Am I creating an empty JSON Obj?
$scope.getAllItems(100,0, myQuery);
Is there any better solution to achieve this?
There may be better, more concise ideas available, but this is what I worked out for myself.
In my service ...
fetch : function(page, perpage) {
var query = // build the query
// the whole answer to your question might be this line:
query.limit(perpage).skip(page*perpage);
return query.find();
},
fetchCount : function() {
var query = // build the same query as above
return query.count();
},
In the controller...
$scope.page = 0; // the page we're on
$scope.perpage = 30; // objects per page
MyService.fetchCount().then(function(count) {
var pagesCount = Math.ceil(count / $scope.perpage);
$scope.pages = [];
// pages is just an array of ints to give the view page number buttons
for (var i=0; i<pagesCount; i++) { $scope.pages.push(i); }
fetch();
});
function fetch() {
return MyService.fetch($scope.page, $scope.perpage)).then(function(results) {
$scope.results = results;
});
}
// functions to do page navigation
$scope.nextPage = function() {
$scope.page += 1;
fetch();
};
$scope.prevPage = function() {
$scope.page -= 1;
fetch();
};
$scope.selectedPage = function(p) {
$scope.page = p;
fetch();
};
Then paging buttons and results in my view (bootstrap.css)...
<ul class="pagination">
<li ng-click="prevPage()" ng-class="(page==0)? 'disabled' : ''"><a>«</a></li>
<li ng-repeat="p in pages" ng-click="selectedPage(p)" ng-class="(page==$index)? 'active' : ''"><a>{{p+1}}</a></li>
<li ng-click="nextPage()" ng-class="(page>=pages.length-1)? 'disabled' : ''"><a>»</a></li>
</ul>
<ul><li ng-repeat="result in results"> ... </li></ul>
I fixed my recursive function and now its working. Here it is:
$scope.getAllItems = function(queryLimit, querySkip, query, first) {
$http({method : 'GET',
url : 'https://api.parse.com/1/classes/myClass',
headers: { 'X-Parse-Application-Id':'XXX','X-Parse-REST-API-Key':'YYY'},
params: {limit:queryLimit, skip:querySkip},
}).success(function(data, status) {
if(first) {
query = data.results;
first = !first;
if(query.length == queryLimit) {
querySkip += queryLimit;
$scope.getAllItems(queryLimit, querySkip, query, first);
} else {
$scope.clients = query;
}
} else {
var newQ = data.results;
for (var i = 0 ; i < newQ.length ; i++) {
query.push(newQ[i]);
}
if(query.length == queryLimit + querySkip) {
querySkip += queryLimit;
$scope.getAllItems(queryLimit, querySkip, query, first);
} else {
$scope.clients = query;
}
}
})
.error(function(data, status) {
alert("Error");
});
};
Simply pushed each element to my empty array, also I was mutating queryLimit instead of querySkip in order to iterate through all the elements.

Angularjs ajax request in Symfony2 and Doctrine json response with relationships

I am trying to work with Symfony2, Doctrine and Angujarjs. There is no problem with Symfony2 or Doctrine but I have issues using an ajax request with angularjs. Either it doesn't load anything and I did make a mistake while loading the json (json comes from Symfony and its working) or if it's working, but the json doesn't contain any of the relationship's data.
So, what's the correct way to
A: create a response for angularjs with relationship data (such as articles and categories)
B: load the requested json into an angularjs variable
Here is my controller.js
var app = angular.module("MyApp", []) .config(['$interpolateProvider', function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
}]);
app.filter('offset', function() {
return function(input, start) {
start = parseInt(start, 10);
return input.slice(start);
};
});
app.filter('htmlToPlaintext', function() {
return function(text) {
return String(text).replace(/<[^>]+>/gm, '');
};
});
app.controller("PaginationCtrl", function($scope, $http) {
$scope.articlesPerPage = 8;
$scope.currentPage = 0;
function htmlToPlaintext(text) {
return String(text).replace(/<[^>]+>/gm, '');
}
// this should load the json from '/admin/jsonallarticles' into the articles variable
$http.get('/admin/jsonallarticles').success(function(data) {
$scope.articles = data;
});
$scope.range = function() {
var rangeSize = 5;
var ret = [];
var start;
start = $scope.currentPage;
if ( start > $scope.pageCount()-rangeSize ) {
start = $scope.pageCount()-rangeSize+1;
}
for (var i=start; i<start+rangeSize; i++) {
ret.push(i);
}
return ret;
};
$scope.prevPage = function() {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};
$scope.prevPageDisabled = function() {
return $scope.currentPage === 0 ? "disabled" : "";
};
$scope.pageCount = function() {
return Math.ceil($scope.articles.length/$scope.articlesPerPage)-1;
};
$scope.nextPage = function() {
if ($scope.currentPage < $scope.pageCount()) {
$scope.currentPage++;
}
};
$scope.nextPageDisabled = function() {
return $scope.currentPage === $scope.pageCount() ? "disabled" : "";
};
$scope.setPage = function(n) {
$scope.currentPage = n;
};
});
This is my symfony2 function
public function jsonallarticlesAction() {
$articles = $this->getDoctrine()
->getRepository('AcmeBlogBundle:Articles');
if ( !$articles ) {
throw $this->createNotFoundException(
'Keine Beiträge gefunden!');
}
$queryArticles = $articles->createQueryBuilder('a')
->where('a.status = :status')
->setParameter('status', 0)
->orderBy('a.createdDate', 'DESC')
->getQuery()
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);;
$articles = array_values($queryArticles);
$response = new Response();
$response->setContent(json_encode($articles));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
EDITED CONTROLLER
I tried using the serializer which comes with Symfony
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$articles = $this->getDoctrine()
->getRepository('AcmeBlogBundle:Articles')
->findAll();
if ( !$articles ) {
throw $this->createNotFoundException(
'Keine Artikel gefunden!');
}
$serializer->serialize($articles, 'json');
return new Response(json_encode($json));
But I receive an error:
A circular reference has been detected (configured limit: 1).
For work with Angular.js you must write Rest API. For this you can use https://github.com/FriendsOfSymfony/FOSRestBundle
And for serialize your entities with needed data use http://jmsyst.com/bundles/JMSSerializerBundle
It compatible with FOSRestBundle.
As example of use those bundles you can look one our project https://github.com/stfalcon-studio/lost-and-found
I ran into the same issue and it was due to the fact that my Entity was related back to the same entity from my second entity on a different field. I just simply created this function in my Entity:
public function removeRelationsThatCauseCircularError()
{
$this->companyEvents = NULL;
}
And run the function before going through the serializer.