AngularJS ng-repeat from array not iterating. (Cordova Android) - javascript

I have a Cordova Android app, running Ionic, and I have a script that gets RSS Feeds from multiple URLs.
To make sure that it doesn't just store the last feeds entries in the local storage, I have made an array where I push each RSS Feeds' entries into it so that I can display all the entires from all the feeds.
This is how I've set up the array:
$scope.$apply(function(){
$scope.entryDB = [];
});
This is how the code for fetching each RSS Feed looks:
db.transaction(function(tx) {
tx.executeSql("SELECT (data) FROM note", [], function(tx,res){
for(var iii = 0; iii < res.rows.length; iii++){
alert(res.rows.item(iii).data);
$http.get("https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=" + res.rows.item(iii).data)
.success(function(data) {
$scope.rssTitle = data.responseData.feed.title;
$scope.rssUrl = data.responseData.feed.feedUrl;
$scope.rssSiteUrl = data.responseData.feed.link;
$scope.entries = data.responseData.feed.entries;
window.localStorage.setItem("entries", JSON.stringify(data.responseData.feed.entries));
$scope.entryDB.push(JSON.stringify(data.responseData.feed.entries));
alert($scope.entryDB)
})
.error(function(data) {
console.log("ERROR: " + data);
if(window.localStorage["entries"] !== undefined) {
$scope.entries = JSON.parse(window.localStorage["entries"]);
}
});
}
});
}, function(err){
alert("An error occured while displaying saved notes");
});
(res.rows.item(iii).data is each feed's URL)
The weird thing is that when I try to display the entries using ng-repeat, if I use the entryDB array, it only outputs the entire array as one entry in HTML, but if I use the localStorage "Entries", it works perfectly fine by iterating properly and displaying multiple card items.
I have tried doing alert() to both the localStorage entry and the entryDB entry and they look identical, but ng-repeat won't iterate over the entryDB entries.
This is how I'm trying to display the entires:
<ion-content ng-controller="FeedController" ng-init="init()" class="has-tabs-top">
<!-- // List of Cards // -->
<div class="list card" ng-repeat="entry in entryDB">
<!-- // Card Title // -->
<div class="item item-divider">{{entry.link}}</div>
<!-- // Card Contents // -->
<div class="item item-body" ng-click="browse(entry.link)">
<h2><b>{{entry.title}}</b></h2>
<p>{{entry.contentSnippet}}</p>
<p><a class="subdued">{{entry.publishedDate}}</a></p>
</div>
</div>
</ion-content>
If I try to just display {{entry}}, I can see that it's successfully getting the entire entryDB array, but it won't iterate and just displays one card item with the entire array on it.
Been stuck at this now for 2 days and I've tried looking online for hours - IƦve tried adding 'track by $index' to the ng-repeat but that didn't work either.
I'm a complete newbie when it comes to angularJS so would appreciate if someone could help me out!

Change this line $scope.entryDB.push(JSON.stringify(data.responseData.feed.entries));
to
$scope.entryDB.push(data.responseData.feed.entries);

Related

Angular 4 *ngFor, ngx-pipes get name of top-level key

I'm using the ngx-pipes in my ionic 3 app because I am pulling an object of objects from firebase.
I retrieve my objects and turn it into a variable that I can use on the page:
getEvents() {
this.firebaseDatabase.getEvents.subscribe(data => {
console.log("Events ", data);
this.events = data;
}, error => {
console.log("Events ", error);
});
}
I log the data and it comes back like this:
eventIDHashed_1:
endDateTime:"tomorrow"
location:"somewhere"
roles:
GyyapYhHQDOriruHLvGPKaTOiRp2:"admin"
startDateTime:"today"
title:"Arisss & Nathan"
type:"wedding"
eventIDHashed_2:
endDateTime:"tomorrow"
location:"somewhere"
roles:
GyyapYhHQDOriruHLvGPKaTOiRp2:"admin"
startDateTime:"today"
title:"Jack & Marlana"
type:"wedding"
The way I'm displaying it on the page is a temporary solution, but everything is working fine except the first line. I need to get the event name (the key) where it says eventIDHashed_1 and eventIDHashed_2
<div class="event-container">
<div *ngFor="let event of events | values; let i = index">
<span>{{events[i]}}</span>
<span>{{event.title}}</span>
<span>{{event.location}}</span>
<span>{{event.type}}</span>
<span *ngFor="let role of event.roles | pairs">
<span>{{role[0]}}, {{role[1]}}</span>
</span>
<span>{{event.startDateTime}}</span>
<span>{{event.endDateTime}}</span>
</div>
</div>
I have everything working and am able to retrieve all information, except the actual event ID <span>{{events[i] | keys}}</span> This gives me a list of all of the keys inside of it (endDateTime, location, title, startDateTime...), but I need to get the id of the event eventIDHashed_1 and eventIDHashed_2
After playing with ngx-pipes, I found that I could use the pairs operator fairly simply. I've changed the template from the above to this:
<div *ngFor="let event of events | pairs">
<span>{{event[0]}}</span>
<span>{{event[1].title}}</span>
<span>{{event[1].location}}</span>
<span>{{event[1].type}}</span>
<span *ngFor="let role of event[1].roles | pairs">
<span>{{role[0]}}, {{role[1]}}</span>
</span>
<span>{{event[1].startDateTime}}</span>
<span>{{event[1].endDateTime}}</span>
</div>
ngx-pairs gives me the key (position [0]) and the value (position [1]) of the event

ng-repeat not rendering data from array

I am working on a web app where non-profit organizations can create a profile and be easily searchable by various parameters. In the "create and organization" form, I have a nested array where the organization can add donations that they need. The array is storing ok (I can add multiple donations), however when I try to display it using ng-repeat, nothing renders. When I don't use the ng-repeat and just display via {{ ctrl.organization.donations }} the information shows up with brackets and quotation marks.
Here is the code that I use to add the donations (via the newOrganization controller):
function NewOrganizationController(OrganizationService, CategoryService, $stateParams, $state, $http, Auth){
var ctrl = this;
CategoryService.getCategories().then(function(resp) {
ctrl.categories = resp.data;
});
ctrl.donations = [{text: ''}];
Auth.currentUser().then(function(user) {
ctrl.user = user;
})
ctrl.addNewDonation = function() {
var newDonation = ctrl.donations.length+1;
ctrl.donations.push({text: ''});
};
ctrl.removeDonation = function() {
var lastItem = ctrl.donations.length-1;
ctrl.donations.splice(lastItem);
};
ctrl.addOrganization = function() {
var donations = this.donations;
var allDonations = [];
for (var key in donations) {
if (donations.hasOwnProperty(key)) {
var donation = donations[key].text;
allDonations.push(donation);
}
}
var data = {
name: ctrl.organization.name,
description: ctrl.organization.description,
address: ctrl.organization.address,
donations: allDonations.join("/r/n"),
category_id: this.category.id
};
OrganizationService.createOrganization(data);
$state.go('home.organizations');
};
}
angular
.module('app')
.controller('NewOrganizationController', NewOrganizationController);
Here is the code that I am using to display the array on my show page (this is what shows up with brackets, i.e. donations needed: ["food", "clothing"]):
<h5>{{ ctrl.organization.donations }}</h5>
This is the ng-repeat code that is not rendering anything to the page:
<li class="list-group-item" ng-repeat="donation in donations track by $index">
{{ donation }}
</li>
I've tried to use .join(', ') within the {{donation}} brackets, but this isn't recognized as a function.
edit: After taking AJ's suggestion here is a screenshot of what appears...anyone know how to fix this?
seems that my array is showing up in table form, with each row containing one character
Any help would be greatly appreciated. Here is a link to the github repo in case you want to look at anything else or get a bigger picture.
You need to use the same variable name that works in the h5
<li class="list-group-item" ng-repeat="donation in ctrl.organization.donations track by $index">
{{ donation }}
</li>

Vue.js: How to map a list of keys to Firebase objects?

I develop a small web-app based on Vue.js using Firebase to store and sync the data. I store items (e.g. with attributes title and subtitle) and lists with an attribute listitems, where an array of keys (those generated from Firebase) of items is stored. The structure looks like this:
Now the problem: I want to display a list and show the items from the listitems attribute and I'm doing it like this:
Compontent:
var ShowList = Vue.extend({
template: '#show-list',
firebase: {
// get all existing items from firebase
items: firebase.database().ref('items')
},
data: function () {
// get list item keys of list 'list_id' and bind it to this.list
this.$bindAsObject('list', listsRef.child(this.$route.params.list_id));
return {
list: this.list
};
}
});
Template:
<!-- show a list -->
<template id="show-list">
<ul v-if="list.items != ''">
<li v-for="key in list.items"> <!-- I would like to not being forced to -->
<template v-for="item in items"> <!-- iterate the whole list of existing items -->
<span v-if="item['.key'] == key">
{{ item.title }}
</span>
</template>
</li>
</ul>
<div v-else>No items.</div>
</template>
As you can see, I have to use two iterations where I iterate the full items list for every entry in list.items.
My question: Is there a more efficient way to map the actual objects to the list of object keys? For a huge number of item records, my approach will be very slow. Maybe I'm just too blind to see a simpler solution?
Thanks for your time!
I think you have to denormalize/duplicate some data there. I had a similar situation and this Firebase video cleared a lot of things up for me: https://youtu.be/ran_Ylug7AE?t=2m22s (Link updated to passage at 2:22. The whole serie is worth watching btw.)
My shot at it would be adding (Firebase) keys in "listitems", just like you have done in "items", with only the most crucial data there, so that you can link to a full description
Is your data read only? In which case you could move the filter logic from your template to your data module, like so (I expect I have unintended side-effects):
data: function () {
// get list item keys of list 'list_id' and bind it to this.list
this.$bindAsObject('list', listsRef.child(this.$route.params.list_id));
var items = firebase.database().ref('items')
var activeItems = this.list.items.map(function(key) {
return items[key]
})
return {
activeItems: activeItems;
};
}

How to add Contact List data into PhoneGap ListView

I have a javascript function which will read the device ContactList and add them into a javascript array.In my HTML page i have taken a listview.Now as per my requirement i have to add these array data into the listview by jquery dynamically which i am not able to do .I am not able to see anything on the screen of the mobile on launching the app..
Here is my javascript code to read from Mobile's contact list..
function onDeviceReady() {
// specify contact search criteria
var options = new ContactFindOptions();
options.filter=""; // empty search string returns all contacts
options.multiple=true; // return multiple results
filter = ["displayName"]; // return contact.displayName field
// find contacts
navigator.contacts.find(filter, onSuccess, onError, options);
}
var names = [];
// onSuccess: Get a snapshot of the current contacts
//
function onSuccess(contacts) {
for (var i=0; i<contacts.length; i++) {
if (contacts[i].displayName) { // many contacts don't have displayName
names.push(contacts[i].displayName);
}
}
alert('contacts loaded');
}
and here is my HTML listview..
<div data-role="page" id="home" data-theme="c">
<div data-role="content">
<div id="header" class="header">
<h1>Contact Directory</h1>
</div>
<ul data-role="listview" id="contactlist" data-theme="a">
</ul>
</div>
</div>
So, My question is how can i add the array values into the listview by jquery dynamically..
Thanks..
Couple of ways, but here is one way.
Create a simple string variable to hold your LIs.
Loop over names and append to the string <li> + names[x] + </li> where X is your loop counter.
Use jQuery to get the UL dom and then do .html(s) where s is your string.
Basically you are injecting <li>...</li><li>...</li> into your UL.
The last step is to refresh the list view so jQuery displays it correctly. This is done with the refresh API, defined here: http://api.jquerymobile.com/listview/#method-refresh

Filter variable not updating in controller angularjs

Hi Im attempting to build functionality around the length of a filter in angularjs, and although its working as it should in the view, in the controller the variable seems to stay outdated...
When I click on the div below it filters a list and calls the filterby function. The output of the length of the newly filtered list updates in the view correctly. However in the function itself I have a log set and it is still showing the old length when I click on the div.
<div ng-repeat="filter in filters" ng-click="filterby(filter.filter_type)">{{filter.filter_type}}</div>
<ul>
<li ng-repeat="event in filtered = (events | filter:query) | orderBy:'-event_date' ">
<span >{{event.event_date}},{{event.event_name}}, {{event.event_venue}}, {{event.event_description}} </span>
</li>
</ul>
<br />Length of filtered items {{filtered.length}}
And my view....
$scope.filterby = function(filterby) {
if (filterby == 'ALL') {
$scope.query = '';
}
else {
$scope.query = filterby;
}
console.log($scope.filtered.length);
};
My filter data:
$scope.filters = [
{'filter_type' : 'ALL'},
{'filter_type' : 'Macnass'}
];
EDIT: Ok its not that it nots working at all, its just showing the previous value, as if its one click behind all the time, so its something to do with the fact that the variable in the view is updated after the list is made. but Im not sure how to go about insuring the variable in the controller is the latest value.
Plunker: http://plnkr.co/edit/u7KpqYx8gDwaaXEvGeMn?p=preview
check out the plunker
added below
$scope.filtered = $filter('filter')($scope.events, $scope.query)
in $scope.filterby function

Categories

Resources