I am learning Angular, so here is my testapp : http://enrolin.in/test/#/students
Now here I want to search the database by name. So I created the php that returns exactly what I need. Here is the php : http://enrolin.in/test/login.php?p=fetchbyname&&name=ak You have to replace name in the url to anything you need to search. I also created a partial page that returns absolutely correct results, here is the page: http://enrolin.in/test/#/studentSearch/ak Everything was fine till now But here is the problem:
When I try to search in http://enrolin.in/test/#/students , angularJS does not route me to something like http://enrolin.in/test/#/studentSearch/ak but instead to the default that I have set in $routeProvider
Here is my angularJS (I have removed some unimportant code):
The route provider:
.config(function ($routeProvider) {
$routeProvider
.when("/students/:id", {
templateUrl: "templates/studentDetails.html",
controller: "studentDetailsController"
})
.when("/studentSearch/:name", {
templateUrl: "templates/studentSearch.html",
controller: "studentSearchController"
})
.otherwise({
redirectTo: "/home"
})
})
The Controller that passes the link:
.controller("studentsController", function ($scope, $http, $route,$location) {
$scope.searchStudent=function(){
if($scope.name){
$location.url("/studentsSearch/" + $scope.name);
}
else{
$location.url("/studentsSearch/");
}
}
$scope.reloadData=function(){
$route.reload();
}
$http.get("http://enrolin.in/test/login.php?p=fetchall")
.then(function (response) {
$scope.students = response.data;
})
})
The controller that fetches data and displays:
.controller("studentSearchController", function ($scope, $http, $routeParams) {
if($routeParams.name)
{
$http({
url: "http://enrolin.in/test/login.php?p=fetchbyname&&name=",
method: "get",
params: { name: $routeParams.name }
}).then(function (response) {
$scope.studs = response.data;
})
}
else
{
$http.get("http://enrolin.in/test/login.php?p=fetchall")
.then(function (response) {
$scope.students = response.data;
})
}
})
Previously everytime I wanted to put a link in html to route I used to write like courses But now when I want to put it in the function instead, I am not sure what to write. Please Help.
Hi #AkhilEshKhajuria,
You are not using the same name what you have mentioned in the routing config. Routing name is "/studentSearch/:name?" but you have used in the function as "/studentsSearch/".
Please try replacing $location.url("/studentsSearch/" + $scope.name); with $location.path("/studentsSearch/" + $scope.name);
Correct the naming issue and it should work.
I tried this and it works fine.
Related
I want to pass the data in $rootScope of users
Here is my factroty
userProvider.js
'use strict';
app
.factory('userProvider', function ($rootScope , $http , $location) {
var url='http://127.0.0.1:100/suitecrm/API/Login.php';
function logIn(user) {
$http.post(url,user)
.success(function (response) {
$rootScope.user=response.data;
$location.path('/profile');
console.log(response);
});
}
return {
logIn: logIn
}
});
console.log(response); show me data normally in the console
Here is the controller of the profile which i want to show information of current user
'use strict';
app
.controller('Profile', function ($scope ,userProvider, $rootScope) {
console.log($rootScope.user);
})
;
But in the console of chrome shows me undefined.
Here is Routing.js
'use strict';
var cacheActive=false;
app.config(function ($stateProvider) {
$stateProvider
.state('homapage', {
cache: cacheActive,
url: '/login',
templateUrl: 'js/views/homepage/Login.html',
controller:'homepageLogin'
})
.state('profile', {
cache: cacheActive,
url:'/profile',
templateUrl:'js/views/profiles/profile.html',
controller:'profile'
})
});
How can i pass the data in $rootScope and show them in the view of the controller?
Thank u
You haven't called the logIn() function from your userProvider service yet.
app
.controller('Profile', function ($scope ,userProvider, $rootScope) {
userProvider.logIn($scope.user);
console.log($rootScope.user);
})
But,
I suggest you do it without using $rootScope. What you can is from your factory, you may want to return the data after the call:
app.
factory('userProvider', function($http){
var url = 'http://127.0.0.1:100/suitecrm/API/Login.php';
function logIn(user) {
$http.post(url,user).success(function (response) {
return response;
});
}
return {
logIn: logIn
}
})
Then, again, without using $rootScope, on your Profile controller you can do:
app.
controller('Profile', function($scope, userProvider){
$scope.user = {...}
$scope.currentUser = userProvider.logIn($scope.user);
console.log($scope.currentUser)
})
For the location routing, please do it inside your controller, instead of the factory.
I am new to AngularJs and i have an issue that when i run my app, the factory function call twice time. I want to prevent by calling function from Factory function.
Here is my code:-
advisoryApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.html',
controller: 'mainCtrl'
})
.when('/about', {
templateUrl: 'pages/about.html',
controller: 'aboutController'
})
.when('/contact', {
templateUrl: 'pages/contact.html',
controller: 'contactController'
});
});
advisoryApp.factory('HttpResponse', function ($http) {
return{
getHttpResponse: function (method, url, data) {
return $http({
url: url,
method: method,
data: data
})
}
});
advisoryApp.controller('mainCtrl', function ($scope, HttpResponse, $rootScope) {
$scope.allAdvisoryData = '';
var segment_id = 5;
var url = $rootScope.base_url + "web_service/call_listing/" + segment_id;
var data = 'segment_id=' + segment_id;
$scope.message = 'Everyone come and see how good I look!';
HttpResponse.getHttpResponse('POST', url, data).success(function (data) {
console.log(data);
});
});
Here is my output:-
Here api i.e POST http://localhost/advisory_mandi/web_service/call_listing/5 call twice but i want, it should call only one time.
Most common reason is that you initialise your controller twice.
Few options:
Controller initialised from router and from html with ng-controller
Application initialised twice. Maybe you call ng-app twice
Application bootstrapped from javascript and also from html
I am using UI-Router and want to change routing to be 'component based'. So Instead of defining a controller / template I want to use it like this:
.state('issue', {
url: '/someUrl/:number',
template: '<my-directive></my-directive>',
resolve: {
data: function(dataService) {
return dataService.getData().then(function(response) {
console.log(response.data);
return response.data;
});
}
}
})
Now, I know that with Angular's ngRoute I can use resolved data directly in the template, for example:
$routeProvider
.when('/', {
template: `<my-directive data="resolve.data"></my-directive>`,
resolve: {
data: function (dataService) {
return dataService.getData();
}
}
})
I couldn't do it using UI-Router (value was undefined).
Am I doing something wrong? Is it possible using ui-router?
The point with UI-Router is - result of resolve is available for a controller (related to template). So, we could do it like this:
.state('issue', {
url: '/someUrl/:number',
template: '<my-directive data="stateCtrlData"></my-directive>',
controller: function($scope, data) { $scope.stateCtrlData = data },
resolve: {
data: function(dataService) {
return dataService.getData().then(function(response) {
console.log(response.data);
return response.data;
});
}
}
})
The data are passed into controller and from its scope we pass it to directive.
If you mean injecting your data service, then you can do it like this (remember that the '' is telling to inject):
state('issue', {
url: '/someUrl/',
template: '<my-directive data="pep.data"></my-directive>',
controller: function( data) { this.data = data },
controllerAs: 'pep',
resolve:{
dataSvc : 'YourDataSvc',
campaign : function(dataSvc){
return dataSvc.getData();
}
}
Please remember a ui-view will be expected if you want to put additional views or child states.
Actually you can (tested only in ui-router v0.3.2)
There's an undocumented $resolve variable which is automatically injected in the controller.
Simply add 'controllerAs' property to the state as follows, and you can use $resolve in the template:
.state('issue', {
url: '/someUrl/:number',
template: '<my-directive data="vm.$resolve.data"></my-directive>',
controllerAs: 'vm',
resolve: {
data: function(dataService) {
return dataService.getData().then(function(response) {
console.log(response.data);
return response.data;
});
}
}
})
I am receiving an external object from WordPress, in one view I have the post.title, and if you click in that title you can go to another view and see te entire post.content.
So far, I can not see the entire post because I am getting a couple errors, posts is undefined.
I made a Plunkr, CodePen and one JSBin for you to understand easier. If you use JSBin is better because you can use the console which is integrated there. All you have to do is click on the title of the post, and you are going to realize that can not go to the other view.
Here is the code regarding my issue, which is the same you will see in the online editors I post above
.state('tabs', {
url: "/tabs",
abstract: true,
templateUrl: "tabs.html"
})
.state('tabs.news', {
url: "/news",
views: {
'tab-news': {
templateUrl: "tab-news.html",
controller: 'NewsCtrl'
}
}
})
.state('tabs.post-detail', {
url: '/news/:postId',
views: {
'tab-news': {
templateUrl: 'tab-post-detail.html',
controller: 'PostDetailCtrl'
}
}
})
the html for the main view, news
<a ng-href="#/tabs/news/{{post.ID}}">
<h2 ng-bind-html="post.title"></h2>
<p>{{post.date | date}}</p>
</a>
and here is the view where you can not enter yet, the view where are redirected after clicking in the title on the main view
<div>
<h3>{{:: post.title}}</h3>
<p>{{:: post.content}}</p>
</div>
now the controller for the main view
.controller('NewsCtrl', function($scope, $ionicLoading, FreshlyPressed) {
$scope.posts = [];
$scope.doRefresh = function() {
$scope.posts = FreshlyPressed.getBlogs($scope);
}
});
here the service
angular.module('urbanet.app.service', [])
.service('FreshlyPressed', function($http) {
return {
getBlogs: function($scope) {
$scope.posts = [];
$http.jsonp('https://public-api.wordpress.com/rest/v1.1/freshly-pressed?callback=JSON_CALLBACK')
.success(function(result) {
$scope.posts = result.posts;
});
},
get: function(postId, $scope) {
console.log(postId);
console.log($scope.posts);
for (var i = 0; i < $scope.posts.length; i++) {
if ($scope.posts[i].id === parseInt(postId)) {
return $scope.posts[i];
}
}
return null;
}
}
})
and controller for the second view, the view of the entire post
.controller('PostDetailCtrl', function($scope, $stateParams, FreshlyPressed) {
$scope.post = FreshlyPressed.get($stateParams.postId, $scope);
});
You are going to have to make a new request for individual posts
The freshly-pressed api returns to you a siteID and postId.
You then combine those to use the posts API to get the single post.
Since freshly-pressed is a constantly changing list, this is the only way you would ever be able to bookmark posts. Tomorrow you may not get the same set of main posts, so wouldn't be able to replicate links that were used today the way you are attempting to
Service method:
getPostById: function(siteId,postId ) {
var url ='https://public-api.wordpress.com/rest/v1.1/sites/'+siteId+'/posts/'+postId+'?callback=JSON_CALLBACK'
return $http.jsonp(url)
}
controller
.controller('PostDetailCtrl', function($scope, $stateParams, FreshlyPressed) {
var postId = $stateParams.postId,
siteId = $stateParams.siteId;
FreshlyPressed.getPostById(siteId,postId).success(function(response){
$scope.post = response
})
});
Modify links accordingly
<a ng-href="#/tabs/news/{{post.site_ID}}/{{post.ID}}">
Working demo
.controller('PostDetailCtrl', function($scope, $stateParams, FreshlyPressed) {
$scope.post = FreshlyPressed.get($stateParams.postId, $scope);
});
This is a problem. You are trying to pass the entire $scope object as a parameter?
What exactly do you want to pass to the get call?
You have this:
get: function(postId, $scope) { //<- that shouldn't be $scope, make it 'post' or something
console.log(postId);
console.log($scope.posts); //Notice that this comes back undefined?
for (var i = 0; i < $scope.posts.length; i++) { //<- length throws an error because there isn't anything there.
if ($scope.posts[i].id === parseInt(postId)) {
return $scope.posts[i];
}
}
return null;
}
You shouldn't be trying to pass $scope as a param to your service then access $scope inside the factory.
Have your service store your posts data and return that data to your controllers. You can do something like this:
How to make multiple http requests?
Don't try to pass in $scope. Just send the post id to the service and return the data you need.
As #tpie and #charlietfl already mentioned, the current approach (passing $scope as parameter to the service) doesn't work. Another alternative to what tpie suggested (caching the posts data in the service) might be using resolve and promises:
Service code
.service('FreshlyPressed', function($q, $http) {
return {
getBlogs: function() {
var deferred = $q.defer();
$http.jsonp('https://public-api.wordpress.com/rest/v1.1/freshly-pressed?callback=JSON_CALLBACK')
.success(function(result) {
deferred.resolve(result.posts);
});
return deferred.promise;
},
get: function (postId, posts) {
/* snipped, this wasn't the problematic part */
}
}
})
This won't cache the posts result in your service, which might be a downside if the $http call you are making is heavy, but using promises is a nice way of setting up asynchronous requests.
Then corresponding state config
.state('tabs', {
url: "/tabs",
abstract: true,
templateUrl: "tabs.html"
})
.state('tabs.news', {
url: "/news",
views: {
'tab-news': {
templateUrl: "tab-news.html",
controller: 'NewsCtrl'
}
},
resolve: {
posts: function (FreshlyPressed) {
return FreshlyPressed.getBlogs();
}
}
})
.state('tabs.post-detail', {
url: '/news/:postId',
views: {
'tab-news': {
templateUrl: 'tab-post-detail.html',
controller: 'PostDetailCtrl'
}
},
resolve: {
posts: function (FreshlyPressed) {
return FreshlyPressed.getBlogs();
}
}
})
This will invoke the getBlogs function in your service and wait for the promise to be resolved. After that, you can inject the resolved posts variable into your controllers:
and finally controllers
.controller('NewsCtrl', function($scope, $ionicLoading, FreshlyPressed, posts) {
$scope.posts = posts;
$scope.doRefresh = function() {
FreshlyPressed.getBlogs()
.then(function (posts) {
$scope.posts = posts;
});
}
});
Here we can set up the $scope.posts variable directly using the resolved posts variable. The doRefresh function needs then to be modified so that it will invoke the service function and after the promise is resolved, set the $scope.posts data accordingly.
.controller('PostDetailCtrl', function($scope, $stateParams, FreshlyPressed, posts) {
$scope.post = FreshlyPressed.get($stateParams.postId, posts);
});
And here we give the service get function the resolved posts variable as parameter, as in this case the service isn't caching that data.
This isn't problem-free approach, for example consider following scenario: you get one set of posts data into your main controller. Then, there are new posts posted into the wordpress you are querying, before your user clicks on a title. This might cause the PostDetailCtrl to receive a new set of posts data, that doesn't any longer contain the certain post that your user clicked.
I think this is anyway a viable alternative, and at least a bit of food for thought.
I have been all over the tutorial sites and couldn't get this working
I'm trying to make an angular app that works over the REST with my server(I downloaded this and managed to get it working but I started a new one from scratch to understand everything better). making the REST server was the easy part since I'm a php guy, but I'm not so familiar with angular part.
I made a simple directory with yeoman and put my REST server next to it in another folder, so I have :
root
------app with all angular code here
------engine which is a yii2 framework
in app/script/app.js I have:
'use strict'; // BTW what is this line doing?
var app = angular
.module('gardeshApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/post/index' , {
templateUrl: 'views/post/index.html',
controller : 'PostList'
})
.otherwise({
redirectTo: '/'
});
});
I wanted make some kind of Model object to put received data in, so I created a Post model like :
app.factory('Post' , ['$resource'] , function($resource){
var Post = $resource('http://localhost/testApp/engine/web/post/:id' , {id : '#id'} , {update: {method: 'PUT'}});
angular.extend(Post.prototype , {
save: function (values) {
if (values) {
angular.extend(this, values);
}
if (this.id) {
return this.$update();
}
return this.$save();
}
});
});
and a controller to fetch the data:
app
.controller('PostList', ['$scope', '$http' , '$resource',
function($scope, $http) {
// $http.get('http://localhost/testApp/engine/web/post').success(function(data){
// console.log(data); // this works fine and gets the json ed data
// });
var posts = new Post();
console.log(posts.query());
}]);
I don't want to call $http.get myself, I want to make it dynamic but the Error says Post is not defined.
how can I make a proper Post Object to represent the model I'm fetching?
You may do something like this:
app.factory('Post' , ['$resource'] , function($resource){
var Post = $resource('http://localhost/testApp/engine/web/post/:id',
{
update: {method: 'PUT'}
}
);
return Post;
});
And,
app.controller('PostList', ['$scope', '$http' , 'Post',
function($scope, $http, Post) {
console.log(Post.query());
}]);
You need to return your built object in a factory in order to make it dependency-injectable later. Then in your controller, you need to declare that your want Post, and Angular will inject it for you.