displaying data from Firebase with angular - angularjs

I am trying to display a table of posts following this tutorial:
http://code.tutsplus.com/tutorials/creating-a-web-app-from-scratch-using-angularjs-and-firebase--cms-22391
Part 5 has still not been published, so I took the tutorial all the way to part 4 and am trying to build a post.html view. However, as a beginner in both angular and firebase, I am really struggling.
Here is the code for my post/post.js file:
'use strict';
angular.module('myApp.post', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/post', {
templateUrl: 'post/post.html',
controller: 'PostCtrl'
});
}])
.controller('PostCtrl', ['$scope','$firebase' , function($scope,$firebase) {
$scope.message = 'Hello World';
$scope.viewPost = function(){
$scope.article.title = "";
$scope.article.post = "";
$scope.article= {};
$scope.myData = new Firebase("https://glowing-fire-6133.firebaseio.com/Posts");
};
$scope.myData.on('value', function(snapshot){
$scope.article = snapshot.val();
});
}]);
And here is the code for my post.html file
<title></title>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/css/blog.css" rel="stylesheet">
</head>
<body ng-controller="PostCtrl">
<h1>{{message}}</h1>
<div ng-repeat="post in posts">
<h2>{{article.title}}</h2>
<div>{{article.post}}</div>
</div>
</body>
</html>
I get no errors or results from this. I made sure to add the
'myApp.post', //Post view
module to app.js and the in the index.html but still nothing.
Am I doing or missing something really stupid? I.E. login to the DB etc.?
Thanks for your patience
##Addpost script
'use strict';
angular.module('myApp.addPost', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/addPost', {
templateUrl: 'addPost/addPost.html',
controller: 'AddPostCtrl'
});
}])
.controller('AddPostCtrl', ['$scope','$firebase',function($scope,$firebase) {
$scope.AddPost = function(){
var title = $scope.article.title;
var post = $scope.article.post;
var firebaseObj = new Firebase("https://glowing-fire-6133.firebaseio.com/Posts");
var fb = $firebase(firebaseObj);
fb.$push({ title: title,post: post}).then(function(ref) {
console.log(ref);
}, function(error) {
console.log("Error:", error);
});
}
}]);

Where is $scope.posts? I don't see it in your controller, so there's nothing to loop through.
You should have $scope.posts = [/* a bunch of post objects*/];
I actually kinda looks like you should be doing <div ng-repeat="post in myData">.

Related

AngularJS overlaps http.get results and limits them to 10 per page

This happens to be my first angularJS application that fetches data from newsapi and displays all the result in an infinite scrolling pattern.
I am getting data but not as expected, the new results overlap the previous ones and limits to 10 per page.
please advice if i am doing something wrong.
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
</script>
<body>
<div class="w3-container" ng-app="myApp" ng-controller="myCtrl">
<p>Today's News:</p>
<div class="w3-card-4" style="width:100px margin:20px" ng-repeat="x in
source">
<img src="{{x.urlToImage}}" style="width:100%">
<div class="w3-container w3-center">
<h2>{{x.title}}</h2>
</div>
</div><br><br>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
var websites = ["the-times-of-india", "google-news", "bbc-news", "mirror",
"reuters", "the-hindu", "the-new-york-times", "the-wall-street-journal"];
for(var i=0; i<websites.length;i++){
$http.get("https://newsapi.org/v1/articles?source=" +websites[i]
+"&apiKey=f483fa2a3f714981afbee1a1996545b4")
.then(function(response) {
$scope.source = response.data.articles;
});
}
});
</script>
</body>
</html>
You are overwriting $scope.source in each loop over the sources. If you need to get all sources you can push it to an array of sources:
app.controller('myCtrl', function($scope, $http) {
var websites = ["the-times-of-india", "google-news", "bbc-news", "mirror",
"reuters", "the-hindu", "the-new-york-times", "the-wall-street-journal"];
$scope.sources=[];
for(var i=0; i<websites.length;i++){
$http.get("https://newsapi.org/v1/articles?source=" +websites[i]
+"&apiKey=f483fa2a3f714981afbee1a1996545b4")
.then(function(response) {
$scope.sources.push(response.data.articles);
});
}
})
Then, you can use the $scope.sources and iterate over each source.
If you need all articles merged in one array, you can use the concat() method for arrays:
app.controller('myCtrl', function($scope, $http) {
var websites = ["the-times-of-india", "google-news", "bbc-news", "mirror",
"reuters", "the-hindu", "the-new-york-times", "the-wall-street-journal"];
$scope.source=[];
for(var i=0; i<websites.length;i++){
$http.get("https://newsapi.org/v1/articles?source=" +websites[i]
+"&apiKey=f483fa2a3f714981afbee1a1996545b4")
.then(function(response) {
if (response.data.articles){
$scope.source.concat(response.data.articles);
}
});
}
})
Now you have a $scope.source with all articles merged into one array.

AngularJs with REST Api

i'm new to angularJs and want to learn more about it, i'm trying to display some users from a fake REST Api, when trying to run my code i got empty page and the console doesn't give me any errors , i don't know where is the error or where i can debug.
app.js
var myApp = angular.module("app", []);
contactsData.service.js look like that :
(function () {
var app = angular.module("app");
app.service("contactDataSvc", function ($http) {
var self = this;
self.getContacts = function () {
var promise1 = $http.get("http://localhost:3000/contacts");
var promise2 = promise1.then(function (response) {
return response.data;
});
return promise2;
}
});
})();
contacts.controller.js
(function () {
var myApp = angular.module("app");
myApp.controller("contactsCtrl", contactsCtrl);
function contactsCtrl(contactDataSvc) {
contactDataSvc.getContacts()
.then(function(data){
this.contacts = data;
});
}
})();
finally my view index.html
<html ng-app="app">
<head>
<title></title>
<script src="angular.js"></script>
<script src="app.js"></script>
<script src="contacts.controller.js"></script>
<script src="contactsData.service.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" />
<!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>-->
</head>
<body class="container">
<div>
<div ng-controller="contactsCtrl as ctrl">
<div class="raw">
<ul class="list-group">
<li class="li-group-item" ng-repeat="obj in ctrl.contacts">
{{obj.name.title + " " + obj.name.first + " " + obj.name.last}}
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
Small correction required in your contactsCtrl
function contactsCtrl(contactDataSvc) {
var vm = this;
contactDataSvc.getContacts()
.then(function(data){
vm.contacts = data;
});
}
You cannot use this inside the then callback as the scope will be different.
Corrected working example here : http://plnkr.co/edit/LLKJipkBbiZ17QjQpw1X
Refer more:
https://www.w3schools.com/js/js_scope.asp
What is the scope of variables in JavaScript?
1 - Is this url correct? http://localhost:3000/contacts
2 - Open the url on any browser, does it return any response ? JSON?
Please check this first to see if the problem is not on the server side.
Firstly inject $scope in controller because anything/data that we want to access over Html from controller needs to be binded on $scope.
So you controller would look like:
(function () {
var myApp = angular.module("app");
myApp.controller("contactsCtrl", contactsCtrl);
function contactsCtrl($scope,contactDataSvc) {
contactDataSvc.getContacts()
.then(function(data){
$scope.contacts = data;
});
}
})();
Secondly from the service you need to return a promise from it only then you will be able to get the data once the response is back from the API.
So,the updated service code is :
(function () {
var app = angular.module("app");
app.service("contactDataSvc", function ($http,$q) {
var self = this;
var defered = $q.defer();
self.getContacts = function () {
var promise1 = $http.get("http://localhost:3000/contacts");
promise1.then(function (response) {
defered.resolve(response.data);
});
return defered.promise;
}
});
})();

angularJS good practise: how to create controllers for complex application?

let assume I need to create a dashboard application that includes users, tasks and messages. I have a theoric knowledge of angularJS only, not real life application and I don't know exactly how to architect an angular application.
<html ng-app="myApp">
<head>
<script src="js/vendor/angular/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body>
<div id="users" ng-controller="usersController"></div>
<div id="tasks" ng-controller="tasksController"></div>
<div id="messages" ng-controller="messagesController"></div>
</body>
</html>
and app.js
var myApp = angular.module('myApp', []);
myApp.controller('usersController', function($scope) {
$scope.users = [{id:1, username:'john'},{id:2, username:'jack'}];
});
myApp.controller('tasksController', function($scope) {
$scope.tasks = [];
$scope.addTask = function(userid, task) {
}
});
myApp.controller('messagesController', function($scope) {
$scope.messages = [];
$scope.addMessage = function(userid, message) {
}
});
I just cannot figure out how taskController can speak with usersContoller or Taskcontroller.
Or should I use something like
myApp.users = {};
myApp.tasks = {};
myApp.messages = {};
Or should I use a service for that ?
and finally how to watch for changes on that users, tasks and messages.

Use scope from multiple controllers on page

So i've split out my UI into subcomponents but then i realise that one of the components requires to be react to a dropdown change which is caught by the parent controller.
I can create a shared service for the variables and i have been able to inject the sub controller so that i can kick off functions BUT.
how do i then use the scope within the sub controller?
var ctrl1= $scope.$new();
$controller('ctrl', { $scope: ctrl1});
ctrl1.GetData();
this works fine. I can see data coming back in the console. BUT my ui doesnt change. What am i missing?
I've edited the post to illustrate what i'm attempting to do more clearly.
The drop down on change is caught by the parent controller but i then require the child controller to run away and get some data and update the UI.
It's an attempt to split out the components. Is this possible? Or have a split the components out too far?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app2', [])
.controller('ctrl2', ['$scope', '$http', function($scope, $http){
$scope.getdata = function(){
$http.post(WebServiceURL)
.success(function(data){
$scope.app2Data = "test2 data";
});
}
}]);
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope','$controller',function($scope, $controller){
$scope.name = 'Controller 1';
//just something to put in the ddp
$scope.data = [
{id:1, name: "test"},
{id:2, name: "test2"}
]
$scope.makeChanged = function(id){
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
var cl2 = $scope.$new();
$controller('ctrl2', { $scope: cl2 });
cl2.getdata();
}
}]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.id)"></select>
<div>
{{app2Data.text}}
</div>
</div>
</body>
</html>
for anyone interested here's how i got round this.
I created a shared service between the two controllers. and created a callback on the service. i registered the call back on ctrl2 so when the shared variable changed the controller2 will do what i want it to and scope is freshed.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope', '$controller', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name1 = 'Controller 1';
console.log('ctrl1');
//just something to put in the ddp
$scope.data = [{
id: 1,
name: 'test'
}, {
id: 2,
name: 'test2'
}];
$scope.makeChanged = function(value) {
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
appointmentSharedProperties.setDetail(value);
console.log('in makeChanged: ' + value);
}
}
]).service('appointmentSharedProperties', function() {
var test = '';
var __callback = [];
return {
getDetail: function() {
return test;
},
setDetail: function(value) {
test = value;
if (__callback.length > 0) {
angular.forEach(__callback, function(callback) {
callback();
});
}
},
setCallback: function(callback) {
__callback.push(callback);
}
};
});
angular.module('app2', [])
.controller('ctrl2', ['$scope', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name2 = 'Controller 2';
console.log('ctrl2');
var getdata = function() {
console.log('in getdata');
$scope.app2Data = appointmentSharedProperties.getDetail();
}
appointmentSharedProperties.setCallback(getdata);
}
]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name1}}</p>
<p>here is: {{name2}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.name)"></select>
<div>
{{app2Data}}
</div>
</div>
</body>
</html>
General example of how to pass variables from one controller to other
<html>
<head>
<meta charset="ISO-8859-1">
<title>Basic Controller</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js">
</script>
</head>
<body ng-app="myApp">
<div ng-controller="ctrl1">
{{greeting}}
</div>
<div ng-controller="ctrl2">
{{dataToHtml2}}
</div>
</body>
</html>
This is the javascript file for this
var myApp = angular.module('myApp',[]);
myApp.service('sampleService', function(){
var temp = '';
this.setValue = function(data){
temp = data;
}
this.getValue = function(){
return temp;
}
});
myApp.controller('ctrl1', function($scope,sampleService) {
$scope.greeting = 'This line is in first controller but I exist in both';
var data= $scope.greeting;
sampleService.setValue(data);
});
myApp.controller('ctrl2', function($scope, sampleService){
$scope.dataToHtml2 =sampleService.getValue();
});
Here is the blog that explains this flow : Frequently asked questions in angularjs
It has the demo of what I written. Happy coding..!!

AngularUI view not updating after model changes

Beginner question on AngularUI updating a view after the model changes. I have a list of recipes and each recipe has a list ingredients. After a $http GET for ingredients, my nested loop isn't updating. Because other ng-repeat posts aren't helping I'm wondering if this is my AngularUI (UI) code.
How should subviews get updated after model changes? Is a scope trigger needed?
index.html:
<body>
<div ui-view></div>
....
#Outer
<script type="text/ng-template" id="front.html">
<div ng-repeat="search in searches" ng-class="{starred: search.isStarred, active: search.isActive, editing: search.isediting}" class="row">
<ng-include src="'grid.html'"></ng-include>
....
#Inner
<script type="text/ng-template" id="grid.html">
<ng-repeat="item in search">
<!-- item in $scope.searches[$index].results -->
<!-- item in $parent[$index].results -->
<li>{{item.searchId}}</li>
<!--<ng-include src="'image-item.html'"></ng-include>-->
app.js:
angular.module('tycho', ['ui.router', 'ui.bootstrap', 'tychoControllers', 'tychoDirectives', 'tychoServices'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/front");
$stateProvider
.state('front', {
url: "/front",
controller: 'tychoController',
templateUrl: 'front.html'
})
controllers.js:
var controllers = angular.module('tychoControllers', []);
controllers.controller('tychoController',
['$scope', '$filter', 'tychoStorage', 'tychoCapi', 'capiSearch', '$http', '$timeout',
function tychoController(
$scope, $filter, tychoStorage, tychoCapi, capiSearch, $http, $timeout)
{
var searches = $scope.searches = tychoStorage.getSearches();
$scope.capi = new tychoCapi();
//.....
$scope.$watch('searches', function (newValue, oldValue) {
$scope.searchCount = searches.length;
$scope.starredCount = $filter('filter')(searches, { starred: true }).length;
$scope.completedCount = searches.length - $scope.starredCount;
if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
tychoStorage.putSearches(searches);
}
}, true);
$scope.runSearch = function (search) {
capiSearch.getResults(search).then(function (data) {
// fix for $$digest busy
$timeout(function () {
var i = $scope.searches.indexOf(search);
if (i > -1 && data.Results && data.Results.length) {
var arr = $scope.searches[i].results || [];
$scope.searches[i].results = arr.concat(data.Results);
console.log('appending to', $scope.searches[i])
}
});
});
};
The app is needs to update $scope.searches[ n ].results=.... in a controller and have the view (view's nested repeat) update too. I feel like scope is wrong.
Try above code in subview:
<ng-repeat="item in search.results as search in searches">
<li>{{item.searchId}}</li>
<!--<ng-include src="'search-grid-item.html'"></ng-include>-->
</ng-repeat>
Thanks Alexand for pointing out a tag issue. Changing code from <ng-repeat... to <div ng-repeat="item in search.results... allowed $scope updates to work from the controller. Awesomeness.

Resources