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
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.
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;
}
});
})();
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.
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..!!
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.