i make straight search engine. Get data from Google Api. My first view is home page and here is only form search and list results. My two view contain player.
My route provider:
$routeProvider.
when('/home', {
templateUrl: 'view/home.html',
controller: 'ZippyListCtrl'
}).
when('/mp3/:wwwId/:zippyId', {
templateUrl: 'view/mp3.html',
controller: 'Mp3DetailCtrl'
}).
otherwise({
redirectTo: '/home'
});
}])
My controllers:
zippycatControllers.controller('ZippyListCtrl', ['$scope', '$http', function($scope, $http) {
$scope.dane = {};
$scope.ladowanie = 0;
var url = "http://ajax.googleapis.com/ajax/services/search/web?callback=JSON_CALLBACK";
$scope.search = function() {
if ($scope.dane) {
$scope.ladowanie = 1;
$http({
url: url,
params: {q: $scope.dane.q, "start": 0, v: "1.0", rsz: "large", "pws": 0},
method: 'JSONP'
}).success(function (responseData) {
//console.log(responseData);
$scope.ladowanie = 0;
$scope.message = responseData;
})
}
}}]);
and:
zippycatControllers.controller('Mp3DetailCtrl', ['$scope', '$routeParams', '$sce', function($scope, $routeParams, $sce) {
$scope.player = $sce.trustAsHtml(
'code player');}]);
My question is: how search on two view?
For different actions on different pages, you can create a factory whose purpose is to get the data and perform a callback function passed to it.
.factory('getResults', ['$http', function($http) {
return function(requestObj, callBackFunc){
var url = "http://ajax.googleapis.com/ajax/services/search/web?callback=JSON_CALLBACK";
$http({
url: url,
params: {q: requestObj.q, "start": 0, v: "1.0", rsz: "large", "pws": 0},//setting to be done based on requestObj params,
method: 'JSONP'
}).success(function (responseData) {
callBackFunc(responseData);
})
}
}])
Now when you call it from the home controller, you can use:
getResults($scope.dane, function(resonseData){
$scope.messageObj.ladowanie = 0;
$scope.messageObj.message = responseData;
});
while in other view you can use:
getResults($scope.dane, function(resonseData){
$scope.messageObj.ladowanie = 0;
$scope.messageObj.message = responseData;
//redirection to home page.
});
Here messageObj should be in the main controller(means attached to html element containing the views , it is usually body level controller) so that the it is available in both the view and both the views are just changing the attributes so the main Object and not the copy is getting changed. In your code, $scope.message is different for different controllers as it creates a seperate copy for each controller.
Now when you get redirected to the home page, you have a search result list already so you can just populate that there.
Hope this helps...
Related
I am making a shop only to learn Angular, but I have problem and I coulnd find the solution anywhere. The site is located locally on my PC. I am not using even the localhost for now.
I have file application.js to set the routes of my site:
'use strict';
var app = angular.module( 'app' , ['ngRoute','controllers'] );
app.config(['$routeProvider','$httpProvider',function($routeProvider, $httpProvider){
$routeProvider.when('/products', {
controller: 'products',
templateUrl: 'partials/products.html'
});
$routeProvider.when( '/product/:id' , {
controller: 'product',
templateUrl : 'partials/product.html'
});
$routeProvider.otherwise({
redirectTo: '/home'
});
}]);
Here is my file with controllers:
'use strict';
var controllers = angular.module('controllers',['ngRoute']);
// display all products
controllers.controller('products',['$scope', '$http',function($scope, $http){
// $scope.displayProducts = function(){
//load data from file
$http({
method: 'GET',
url: 'model/products.json'
}).then(function successCallback(response) {
// display the data
$scope.products = response.data;
}, function errorCallback(response) {
$scope.products = 'Error downloading data...';
});
// };
}]);
// edit single product
controllers.controller('product',[ '$scope' , '$http' , '$routeParams' ,function($scope, $http, $routeParams){
//load data from file
$http({
method: 'GET',
url: 'model/products.json'
}).then(function successCallback(response) {
// display selected data
$scope.product = response.data[$routeParams.id];
}, function errorCallback(response) {
$scope.product = 'Error downloading data...';
});
}]);
I want the second controller to open the product.html and the user would be able to edit the product. Inside the product.html there is only {{product}}. It all worked when I was using Angular in version 1.3.15, but when I have changed it to Angular version 1.6.10 the {{product}} displays me nothing. Why is that ? There is no error in the console for this.
Doing this MEAN stack tutorial which basically creates a rudimentary reddit-like clone with a main page showing all posts and, for each separate post, a separate page showing the post and its comments.
Everything worked great until I added the resolve property to the 'home' state of $stateProvider, which (as far as I understand) ensures that all posts are loaded from the database before the view is rendered. After I added resolve, the inline HTML for 'home', which prints out the main page, stopped working. If I comment 'resolve' out, it works again.
I have a hard time debugging this because I'm still learning how everything works (total beginner although I have a basic grasp of OOP).
Can anyone catch what's going on? If you want me to format this post better please let me know.
Link to my Github with the code for this project
The files that I have made edits to are:
app.js (i just added mongoose here)
public/javascripts/angularApp.js (angular module file)
models/posts.js (model for posts)
models/comments.js (model for comments)
routes/index.js (get/post requests etc)
views/index.ejs (main view file)
Here's the angular app javascript code (i have commented out 'resolve' here):
var app = angular.module('flapperNews', ['ui.router']);
<!-- POSTS-service -->
app.factory('posts', ['$http', function($http){
// create object o with an array called posts
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts').success(function(data) {
// copy the received data into object o's posts array
angular.copy(data, o.posts);
});
};
return o;
}]);
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl'
/* resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
} */
})
.state('posts', {
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home');
}
]);
<!-- MAIN CONTROLLER -->
app.controller('MainCtrl', ['$scope', 'posts',
function($scope, posts) {
$scope.posts = posts.posts;
<!-- 2way binding eli servicen array päivittyy myös -->
$scope.addPost = function() {
if(!$scope.title || $scope.title == '') { return; }
$scope.posts.push({
title: $scope.title,
upvotes: 0,
link:
$scope.link,
comments: [
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
$scope.title='';
$scope.link='';
};
$scope.incrementUpvotes = function (post) {
post.upvotes += 1;
};
}]
);
<!-- POSTS CONTROLLER -->
app.controller('PostsCtrl', ['$scope', '$stateParams', 'posts',
function($scope, $stateParams, posts){
// fetch post with correct ID from posts service and save it into $scope.post
$scope.post = posts.posts[$stateParams.id];
}]);
You can pass the following:
resolve:{
posts: "posts"
}
And then you can use posts as a dependency in your controller. Alternatively you can just make an $http call in the resolve object to return the promise like this and pass the result into the angular controller.
posts: function($http){
return $http({method: 'GET', url: '/postt'})
.then (function (data) {
return doSomeStuffFirst(data);
});
},
If you want to keep current structure in return of posts factory (and not to get only http.data reponse), you can use $q like this:
app.factory('posts', ['$http', '$q', function($http, $q){
var deferred = $q.defer();
// create object o with an array called posts
var o = {
posts: []
};
o.getAll = function() {
$http.get('/posts').then(function(data) {
// copy the received data into object o's posts array
angular.copy(data, o.posts);
deferred.resolve(o);
});
};
return deferred.promise;
}]);
In this case, you'll get full o object in return of promise (using .then function), so you'll be able to reuse this data.
I want to build a Single Page Website, where my data is stored in a CMS. This CMS accepts Ajax Requests to serve me JSON. This JSON I want to output in my ng-app using the ui-router (I also tried the ngRoute before, with same results).
The Problem is: I need no template. Cause all my data I need comes from the JSON Request. But using no template or templateUrl doesn't affects the controller.
The question is how to output my received data in the HTML? I cant use ng-controller because it binds on only this specific controller. Console.log shows that my data is successfully received, but I found no way to get an output.
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('state1', {
url: '/state1',
template: '<h1>This Is A State</h1>',
controller: function($scope, $http) {
$scope.pageObj = '';
$scope.pageObj.url = '/angular/demo/';
$scope.pageObj.class = 'page-my';
$scope.pageObj.data = 'Empty';
$http
.get('/angular/demo/')
.then(function(result) {
console.log("Data Received");
console.log(result.data);
$scope.pageObj.data = result.data;
});
//console.log(result.data);
console.log("Hello state");
}
});
});
I found a small solution with using factory. The question is still, how do I access my data? Data now is stored by an own controller i guess. I post my updated code below:
var app = angular.module('myApp', ['ngSanitize', 'ngRoute', 'ui.router']).factory("dataService", function($http) {
var data = "";
var getData = function() {
return data;
}
var setData = function(newData) {
data = newData;
}
return {
getData: getData,
setData: setData
};
});
app.controller('FactoryCtrl', ['$scope', '$http', 'dataService', function($scope, $http, dataService) {
$scope.mydata = dataService.getData();
console.log($scope.mydata);
}]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('state1', {
url: '/state1',
template: '<h1>{{pageObj.data}}</h1>',
controller: function($scope, $http, dataService) {
$scope.pageObj = '';
$scope.pageObj.url = '/angular/demo/';
$scope.pageObj.class = 'page-my';
$scope.pageObj.data = 'Empty';
$http
.get('/angular/demo/')
.then(function(result) {
console.log("Data Received");
$scope.pageObj.data = result.data;
//$scope.model.data = dataService.getData();
dataService.setData("a string");
//console.log(dataService.getData());
});
console.log("Hello state");
}
});
});
Using angular ui-router I'm trying to use $state.go() to change to the blogEdit state after creating a new entry with blogCreate to continue editing after saving. When I click to save and trigger addPost() method, it doesnt redirect correctly and I see /#/null as the route in the address bar instead of the expected /blog/post/:postId/edit.
blogModule.controller('PostCreateController', ['$scope', '$state', '$stateParams', 'PostResource',
function ($scope, $state, $stateParams, PostResource) {
$scope.post = new PostResource();
$scope.addPost = function () {
$scope.post.$save(function () {
$state.go('blogEdit', {postId: $stateParams.postId}); // THIS SHOULD REDIRECT TO CONTINUE EDITING POST
});
}
}
]);
blogModule.controller('PostEditController', ['$scope', '$stateParams', 'PostResource',
function ($scope, $stateParams, PostResource) {
$scope.post = PostResource.get({postId: $stateParams.postId});
$scope.updatePost = function () {
$scope.post.$update({postId: $stateParams.postId});
}
}
]);
State route configuration:
var app = angular.module('app', [
'ui.router',
'blogModule'
]);
app.config(['$stateProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('blog', {
url: '/blog',
templateUrl: 'app/blog/view/blog-list.html',
controller: 'PostListController'
})
.state('blogView', {
url: '/blog/post/{postId:[0-9]}',
templateUrl: 'app/blog/view/blog-detail.html',
controller: 'PostViewController'
})
.state('blogCreate', {
url: '/blog/post/new',
templateUrl: 'app/blog/view/blog-create.html',
controller: 'PostCreateController'
})
.state('blogEdit', {
url: '/blog/post/{postId:[0-9]}/edit',
templateUrl: 'app/blog/view/blog-edit.html',
controller: 'PostEditController'
});
}]);
It seems to do this regardless of what state I try to change to.
I suppose you are saving your post on backend. When you perform save (PUT) operation your backend should return you some response. The response should be like HTTP 201 Entity created and there should be location attribute set (f.e. http://example.com/blog/post/1). Then you can get the id from location header like this:
$scope.post.$save(function (createdPost, headers) {
var postId = headers.location.split("/").pop();
$state.go('blogEdit', {postId: postId});
});
Another way is to just ignore headers and return json response from your backend. F.e. {"postId": 1, "title": "New post", ...}. Then you can do something like:
$scope.post.$save(function (createdPost) {
$state.go('blogEdit', {postId: createdPost.postId});
});
The most important is to know API of your backend (what "it returns").
Basically I got a scenario where the API i'm accessing uses a :groupId as a part of the url in many cases. Is there a easy way to avoid passing $routeParams.groupId in each function call?
var app = angular.module('plunker', []);
app.config(["$routeProvider", function($routeProvider) {
$routeProvider.
when("/:groupId/location", {templateUrl: "partials/location.html", controller: "LocationCtrl"});
}]);
/* Controllers */
app.controller('LocationCtrl', function($scope, $routeParams, Location) {
Location.groupId = $routeParams.groupId; /* Is this even possible? I want to have it available to Location instead of the below*/
Location.query();
Location.query({groupId: $routeParams.groupId});
});
/* Services */
app.service("Location", function($resource, $routeParams) {
return $resource("/api/:groupId/location", {}, {
query: {method: "GET", isArray: true}
});
});
I think you can do this:
app.service("Location", function($resource, $routeParams) {
return $resource("/api/:groupId/location", {groupId:12345}, {
query: {method: "GET", isArray: true}
});
});
I haven't tested it, but I believe that's how the documentation reads
If it's any help, since the above answer didn't work for me, I appended .query to the end of the call.
app.service("Location", function($resource, $routeParams) {
return $resource("/api/:groupId/location", {groupId:'#groupId'})
.query({ groupId: 12345 });
});