ng-repeat not rendering data from array - javascript

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>

Related

AngularJS Filter expression not being updated

I have am dealing with two HTML files and one controller. In one HTML file I have a search bar:
<a ui-sref="allSubmissions">
<input id="searchBar" ng-controller="submissions" ng-model="searchString" class="searchBar" type="text" placeholder="Search">
</a>
Along with some other stuff. In a separte HTML file, I have a list of submissions that I populate with ng-repeat:
<div class="container" ng-controller="submissions">
<ul class="subsList">
<ul>
<li ng-repeat="item in submissionCollectionTest | filter: searchString" class="submissionDivider hover">
<span class="ageText">{{item.age}}</span>
<span class="submissionsText">{{item.submission}}</span>
<span class="descriptionText">{{item.description}}</span>
</li>
</ul>
</ul>
</div>
Along with some other code. It makes sense in my complete app that these files be separate, however, I cannot get the search input to tie to the filter expression and automatically update.
In my controller, i have the following scope variable:
myApp.controller('submissions',function($scope){
$scope.searchString = '';
When I click in the search bar, it takes me to the new page with shows all the content populated from the ng-repeat, then I want to filter the content by typing in the search bar. This does work when I have the search bar code in the same place as the content. How can I update "searchString" globally so that the filter responds when it changes? Thanks
You could use a broadcast from one controller and listen in another. If you're using multiple routes, then you'll want to store the search term in a service.
Example: https://jsfiddle.net/h0bd88dc/
function SearchSubmissionsCtrl($rootScope,Service) {
var vm = this;
vm.searchString = Service.searchString;
vm.search = search;
function search() {
Service.searchString = vm.searchString;
$rootScope.$broadcast('search', vm.searchString);
}
}
function SubmissionsCtrl($scope,Service) {
var vm = this;
vm.searchString = Service.searchString;
vm.items = [{
age: 22,
submission: 'Yes',
description: 'Yo'
}, {
age: 5,
submission: 'Derp',
description: 'Hey'
}];
$scope.$on('search', function(e, string) {
vm.searchString = string;
})
}
function Service() {
var service = {
searchString: null
};
return service;
}

collect filtered ng-repeat data to use in controller

I am trying to build a picture library in a responsive grid with data coming down from a Mongo DB. Data from db is in this form. name, image, keyword, bio, reference", searchable,
I start with an ng-repeat to display category selection checkboxes based on the picture keywords. This seems to work fine.
p CATEGORIES:
span.formgroup(data-ng-repeat='category in mongoController.catData')
input.checks( type='checkbox', ng-model='mongoController.filter[category]')
| {{category}}
Here is the factory that sorts and identifies the keyword checkboxes:
getCategories: function (cat) {
return (cat || []).map(function (pic) {
return pic.keyword;
}).filter(function (pic, idx, array) {
return array.indexOf(pic) === idx;
});
}
From there I filter an ng-repeat to display pictures based on the checkbox selection, and/or a search field which works well also.
input.form-control.input-med(placeholder="Search" type='text', ng-model="search.searchable")
br
div.light.imageItem(data-ng-repeat="picture in filtered=( mongoController.allData | filter:search | filter:mongoController.filterByCategory)")
a(data-toggle="modal", data-target="#myModal", data-backdrop="static", ng-click='mongoController.selectPicture(picture)')
img( ng-src='../images/{{picture.image}}_tn.jpg', alt='Photo of {{picture.image}}')
p Number of results: {{filtered.length}}
Functions to display picture lists:
//Returns pictures of checkboxes || calls the noFilter function to show all
mongoController.filterByCategory = function (picture) {
return mongoController.filter[picture.keyword] || noFilter(mongoController.filter);
};
function noFilter(filterObj) {
for (var key in filterObj) {
if (filterObj[key]) {
return false;
}
}
return true;
}
If you click one of the pictures a modal box pops up with all of the input fields where you can edit image specific fields.
The part I am really struggling with is how to gather the usable data from the filtered ng-repeat to use in the controller so when the modal box is up I can scroll right or left through the other pictures that met the criteria of the search.
Any suggestions would help, even why the hell are you doing it this way?
When you declare the ng-repeat that filters the pictures, your filtered variable belongs to the current $scope (which I cannot infer from the question, as it stands). You could associate the filtered variable to a specific controller by using Controller As syntax: (i.e. using <elem ng-repeat="picture in ctrl.filtered = (ctrl.data | filter1 | filterN)"/>)
Example: (also in jsfiddle)
var mod = angular.module('myapp', []);
mod.controller('ctrl', function() {
var vm = this;
vm.data = ['alice', 'bob', 'carol', 'david', 'ema'];
vm.onbutton = function() {
// access here the filtered data that mets the criteria of the search.
console.log(vm.filtered);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="ctrl as vm">
<input ng-model="search" type="text" />
<p data-ng-repeat="item in vm.filtered = (vm.data | filter:search)">
{{item}}
</p>
<p>Items: {{vm.filtered.length}}</p>
<button ng-click="vm.onbutton()">Show me in console</button>
</div>

trouble with search in angular

I'm new to angular and experiencing some difficulty implementing a 'live search' type of feature. I have my JSON set as a variable in a javascript file and I am able to display that in the html with no problem. I then have a 'list' radio box which changes the size of the display. This is functional as well. I run into trouble, however, when accessing the reverse filter option which is denoted with another radio button. The intended result is to filter the book titles in reverse by their name, ye nothing happens. Here is my JSON if you want to see the structure. And below is the code where I try to perform the filter reverse action:
<div class="container result">
<div ng-class="list ? 'col-md-6' : 'col-md-4'" class="books" ng-repeat="books in books | filter:search | orderBy:'books.doc.name':reverse"> <a href="https://address/{{books.doc.name}}" target="_blank">
<img ng-class="list ? 'col-md-2' : 'col-md-12'" ng-src="{{books.doc.thumbnail_590_url}}" alt="Click to read {{books.doc.name}}" title="Click to read {{books.doc.name}}" class="img-thumbnail" /></a>
<h4 ng-class="list ? 'col-md-10' : 'col-md-12'">{{books.doc.name}}</h4>
</div>
and heres the js:
angular.module("myApp",["ngSanitize"])
.filter('replace', function () {
var pat = / /gi;
return function (text) {
var clean = text.replace(pat, "-");
var temp = clean.split("---");
if (temp.length>1) {
clean = temp[0];
}
return clean;
};
})
.controller("Example", function($scope, $interval) {
$scope.search = "orig";
$scope.books = books;
$scope.reverse = false;
$scope.list = false;
});
I figured this out. Angular filter will not work on a json object, rather the data must be in the form of a json array. I removed the highest level enclosing curly brackets and replaced them with square brackets in addition to removing the numbers and colons like "1272:" that can be seen in the json file I posted. Taking these steps converted my data to a json array and allowed me to use the live search functionality.

Saving an item through factory casts an error with AngularJS and Firebase

I'm using Firebase and AngularJS bundled up together and as I'm in the learningprocess of both, I guess. I'm having some trouble saving an item through a factory with Angular.
This is my script
var app = angular.module('LinkApp', ['firebase']);
app.constant('FirebaseLinks', 'https://[hidden].firebaseio.com/links')
app.controller('LinkCtrl', ['$scope', 'LinksFactory',
function($scope, LinksFactory) {
// get links
$scope.links = LinksFactory.getItems();
// update link
$scope.updateLink = function(link) {
LinksFactory.updateItem(link);
};
}
]);
app.factory('LinksFactory', ['$firebase', 'FirebaseLinks',
function($firebase, FirebaseLinks) {
var ref = new Firebase(FirebaseLinks);
var items = $firebase(ref);
return {
getItems: function() {
return items.$asArray();
},
updateItem: function(item) {
items.$save(item);
}
};
}
]);
This is my html
<div ng-repeat="link in links | orderBy: link.number">
<input type="number" ng-model="link.number" ng-blur="updateLink(link)">
{{ link.name }}: {{ link.url }}
</div>
I'm using my blur function (updateLink) to pass my item into my factory, but from there I get this error: "TypeError: undefined is not a function".
If I pass my item to my function and save my collection from there width $scope.links.$save(link), it is successfull.
How can this be?
Thanks in regards. Say if you need further details.
After a lot of work I figured it out.
I had to return my factory functions and I had to call my variable 'items' with an $asArray() at the end and remove the $asArray() from my getItems function.
But now it works :)

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