I am pretty new to Node.js, Express and angularjs. I am working on a simple Sign-in functionality that will redirect to another page if sign in success. I know I can use window.location for the redirect purpose, but I am trying to use res.render because I also want to pass some values to the new page.
However, the res.render doesn't seem to work, the result page never shows up.
Signin.ejs:
<div id="navbar" class="navbar-collapse collapse" ng-controller="signinController">
<form class="navbar-form navbar-right">
<div class="form-group">
<input type="email" ng-model="inputEmail" placeholder="Email" class="form-control">
</div>
<div class="form-group">
<input type="password" ng-model="inputPassword" placeholder="Password" class="form-control">
</div>
<button type="submit" ng-click="signIn()" class="btn btn-success">Sign in</button>
</form>
</div>
The javascript embedded is:
function signinController($scope,$http,$location) {
$scope.signIn = function() {
$http({
method: 'POST',
url: '/signin',
data: { "inputEmail": $scope.inputEmail, "inputPassword": $scope.inputPassword }
});
};
}
app.js
app.get('/result', home.result);
app.post('/signin', home.afterSignIn);
The home.js
function afterSignIn(req,res)
{
// check user already exists
var sqlStr="select * from users where email='"+req.param("inputEmail")+"' and password='"+req.param("inputPassword")+"'";
console.log("Query is:"+sqlStr);
res.render('result', { result: 'sqlStr' });
}
exports.result=function(req,res){
res.render('result');
}
exports.afterSignIn = afterSignIn;
result.ejs
<%= result %>
Any suggestions or working examples are highly appreciated :)
I think you are bit confused. Use express as the REST engine when it comes to routes. Angular routes will take care of the display logic and view routing on the client side.
I would suggest you to pass JSON data to front end angular and let it do the job for you. For example:
app.get('/', function (req, res) {
res.json({
title : "n562d",
strapline : "Please Log In"
})
});
You can access the API at the endpoint: http://localhost:3000/ Use $resource services to access the express endpoint.
example:
var MyResource = $resource('/');
var myResource = new MyResource();
myResource.$get(function(result){
//result holds -->{title : "n562d", strapline : "Please Log In"}
//use $location to change the uri, which is handled by Angular route config
$location.path('/')
});
For angular routing,i would suggest you to use ui-router.
example:
function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state('index', {
url: "/",
templateUrl: 'app/authorization/index.tpl.html',
controller: 'AuthController'
})
.state('login', {
url: "/login/",
templateUrl: 'app/authorization/login.tpl.html',
controller: 'AuthController'
})
.state('signup',{
url: "/signup/",
templateUrl : 'app/authorization/signup.tpl.html',
controller: 'AuthController'
});
}
]);
Let me know if you need more detailed answer then i will update it. I hope it helps.
Feel free to look for similar implementation here.
Related
I am doing an online tutorial where they teach you to make a simple web-app using MEAN.The code below is for editing the given collection of JSON objects(Videos are JSON objects here)
The collection is at
/api/videos
So I have to click on a href="/#/video/{{video._id}} which takes me to form.html and I have the option of editing the 'title' and 'description' parameters of the JSON object.
What I can't seem to understand is:
a)Why is this (full code below in the question) required
var Videos = $resource('/api/videos/:id', { id: '#_id' },
{
update: { method: 'PUT' }
});
Since I am on href="/#/video/{{video._id}} can't I directly take the id from the URL
var Videos=$resource('api/videos)
Videos.get({ id: $routeParams.id }, function(video){
$scope.video = video;
});
b)Whait is the workflow(i.e when is the router.get() request exactly made and when is the router.put() request made)
According to me when I click on the save button the Controller makes a put request to the API but I can't figure out when the router.get() request is being made
I am trying to read up express and angular documentations but they don't seem to explain the workflow.
Could you also please tell me what should I read up to get a better understanding?
This is the form.html code
<h1>Add a Video</h1>
<form>
<div class="form-group">
<label>Title</label>
<input class="form-control" ng-model="video.title"></input>
</div>
<div>
<label>Description</label>
<textarea class="form-control" ng-model="video.description"></textarea>
</div>
<input type="button" class="btn btn-primary" value="Save" ng-click="save()"></input>
</form>
This is the controller code
app.controller('EditVideoCtrl', ['$scope', '$resource', '$location', '$routeParams',
function($scope, $resource, $location, $routeParams){
var Videos = $resource('/api/videos/:id', { id: '#_id' },
{
update: { method: 'PUT' }
});
Videos.get({ id: $routeParams.id }, function(video){
$scope.video = video;
});
$scope.save = function(){
Videos.update($scope.video, function(){
$location.path('/');
});
}
}]);
This is the API Endpoint Code
router.get('/:id', function(req,res){
var collection =db.get('videos');
collection.findOne({_id: req.params.id},function(err,video){
if(err) throw err;
res.json(video);
});
});
router.put('/:id', function(req, res){
var collection=db.get('videos');
collection.update({_id:req.params.id},
{title: req.body.title,
description: req.body.description
},
function (err,video)
{if (err) throw err;
res.json(video);
});
});
Well, according to AngularJS docs for $resouce, $resource is:
A factory which creates a resource object that lets you interact with
RESTful server-side data sources.
In other words is a shortcut for RESTful services operations. The code bellow creates an interface with an API endpoint to make REST operations more easy to do.
Once you have this:
var User = $resource('/user/:userId', {userId:'#id'});
Is much easier to do this:
User.get({userId:123}, function(user) {
user.abc = true;
user.$save();
});
Because RESTful is a standard, and $resource is the Angular's implementation of the consumption of API's in this standard. On his internals, is made an assynchronous request with the propper headers and method according to the operation you conigured and choosed.
I have an HTML page, once loaded in the user's browser the 'list' state is activated and the 'list' partial is pulled by Angular and populated with a list of servers.
Each server has a 'details' link that specifies the 'details' state for that server.
<td><a ui-sref="details({ serverName: '{{server.name}}' })">Details</a></td>
When rendered the 'ui-sref' generates the expected 'href' url based on the route and its optional parameters.
<a ui-sref="details({ serverName: 'SLCMedia' })" href="#/details/SLCMedia">Details</a>
When clicked it works as expected and the 'details' partial is pulled and in the controller assigned to that state pulls the server with the name specified.
The issue I am running into is the fact that once the 'details' partial is loaded, it too has a 'ui-sref' to an 'edit' state.
<a ui-sref="edit({ serverName: '{{server.name}}' })">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit
</button>
</a>
But when this partial is loaded the 'ui-sref' is not generating the correct 'href' url.
<a ui-sref="edit({ serverName: 'SLCMedia' })" href="#/edit/">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit
</button>
</a>
As you can see the 'href' url is '#/edit/' not '#/edit/SLCMedia' as would be expected. It's got to be something simple that I am missing. Does the change of state have something to do with it?
Here are all of defined 'states' for the page.
// Create the Angular App to rule the Server Management Page
var serverApp = angular.module('serverApp', [
'ui.router',
'serverControllers',
'utilitiesService'
]);
serverApp.config(function ($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/list");
// Now set up the states
$stateProvider
.state('list', {
url: '/list',
templateUrl: '/views/pages/servers/list.html',
controller: 'serverListCtrl'
})
.state('details', {
url: '/details/:serverName',
templateUrl: '/views/pages/servers/details.html',
controller: 'serverDetailsCtrl'
})
.state('create', {
url: '/create',
templateUrl: '/views/pages/servers/create.html'
})
.state('edit', {
url: '/edit/:serverName',
templateUrl: '/views/pages/servers/edit.html',
controller: 'serverEditCtrl'
})
});
Here are my controllers
var serverControllers = angular.module('serverControllers', ['utilitiesService']);
serverControllers.controller('serverListCtrl', function ($scope, $http) {
$http.get('/servers/getList').success(function (data) {
$scope.serverList = data;
});
});
serverControllers.controller('serverDetailsCtrl', function ($scope, $stateParams, $http) {
var serverName = $stateParams.serverName;
$http.get('/servers/getServerByName/' + serverName).success(function (data) {
$scope.server = data;
});
});
serverControllers.controller('serverEditCtrl', function ($scope, $stateParams, $http, $state, showAlertMessage) {
var serverName = $stateParams.serverName;
$http.get('/servers/getServerByName/' + serverName).success(function (data) {
$scope.server = data;
});
$scope.server.submitForm = function (item, event) {
console.log("--> Submitting Server Update");
//TIMDO: Verify all required fields have been included
var responsePromise = $http.post("/servers/postEdit", $scope.server, {});
responsePromise.success(function(dataFromServer, status, headers, config) {
showAlertMessage({
type: 'success',
title: 'Success',
message: 'Server information updated'
});
$state.go('clear');
});
responsePromise.error(function(data, status, headers, config) {
showAlertMessage({
type: 'error',
title: 'Success',
message: 'Server information updated'
});
});
}
});
Hmm, I'm probably misunderstanding your issue but I see at least one obvious difference between the look of your code and the look of mine.
My angular-ui-router links look like this:
<a ui-sref="reps-show({ id: rep.id })">{{rep.name}}</a>
The difference is the absence of braces around rep.id. So I wonder if changing this
<td><a ui-sref="details({ serverName: '{{server.name}}' })">Details</a></td>
to this
<td><a ui-sref="details({ serverName: server.name })">Details</a></td>
might do something for you.
That's probably not it but that's the first thing that came to mind for me.
I created simplified, but working version here. Because there is nothing obviously wrong. This example should at least help you to assure that:
All you are trying to do is supposed to be working.
Here are states:
// States
$stateProvider
.state('list', {
url: "/list",
templateUrl: 'tpl.list.html',
controller: 'serverListCtrl',
})
.state('edit', {
url: '/edit/:serverName',
templateUrl: 'tpl.html',
controller: 'serverEditCtrl'
})
Here controller of a list loading data
.controller('serverListCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('server.json').success(function (data) {
$scope.serverList = data;
});
}])
(server.json) - example of data
[
{"name":"abc"},
{"name":"def"},
{"name":"xyz"}
]
And the same template:
<li ng-repeat="server in serverList">
<a ui-sref="edit({ serverName: '{{server.name}}' })">
<button class="btn btn-lg btn-labeled btn-primary">
<span class="btn-label icon fa fa-edit"></span>
Edit {{server.name}}
</button>
</a>
</li>
All is working as expected. Check it here.
I want to contribute with another datapoint in-case some other folks arrive here with a similar question, as I did.
I was using the non-curly-brace version in my app, and it wasn't working. My specifics involve the InfoWindow in Google Maps. I believe there is a rendering order "issue" such that the data required for the ui-sref link doesn't exist, and when it does finally exist, it's never "re-rendered".
Original (non-working) version:
%h3
{{window_info.data.user.name || "Mystery Person"}}
%a.fa.fa-info-circle{ ui: { sref: 'users.show({id: window_info.data.user.id })' } }
%pre {{window_info.data.user.id | json}}
Working version:
%h3
{{window_info.data.user.name || "Mystery Person"}}
%a.fa.fa-info-circle{ ui: { sref: "users.show({id: '{{ window_info.data.user.id }}' })" } }
%pre {{window_info.data.user.id | json}}
I placed the %pre tag with the info to prove to myself that the datum was in-fact present (at least ultimately/eventually), but even still the original code for the link was not working. I adjusted my code to use the interpolated curly-brace version as per the OPs situation and it worked.
Conclusion: Your solution could depend on the way in which the parent component is handling rendering. Google Maps in this case is fairly notorious for being "funky" (technical term) with rendering, particularly in Angu-land.
I am trying to request some data from node.js server from my angular.js. The problem is that upon data response i see a blank browser window with my json object printed on it. I want angular.js to recognize the response and stay on page.
HTML form - template that gets loaded with loginController
<section class="small-container">
<div class="login-form">
<form action="/login" method="post" ng-submit="processForm()">
<input ng-model="formData.username" type="text" name="username">
<input ng-model="formData.password" type="password" name="password">
<button>login</button>
</form>
</div>
</section>
Angular.JS
var app = angular.module("blavor", ['ngRoute']);
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when("/", {
templateUrl: "/index",
controller: "loginController"
})
.when("/register", {
templateUrl: "/register",
controller: "registerController"
})
.otherwise("/");
$locationProvider.html5Mode(true);
}]);
app.controller('loginController', function($scope, $http) {
$scope.formData = {};
$scope.processForm = function() {
$http({
method: 'POST',
url: '/login',
data: $.param($scope.formData),
processData: false,
responseType: "json",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(data) {
console.log(data);
if (!data.success) {
alert("Noo!");
} else {
alert("YEEEY!");
}
});
};
});
Node.js Server - index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var express = require('express');
var bodyParser = require('body-parser');
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({ extended: false }) );
var routes = require('./routes')(app);
http.listen(3000, function() {
console.log('listening on *:3000');
});
module.exports.start = start;
Node.js Server - routes
module.exports = function(app) {
app.post('/login', function(request, response) {
console.log(request.body);
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify({value:"somevalue"}));
});
}
I am using AngularJS v1.2.24 and Node.js v0.10.25
console.log(data) in angular never gets called..
Hi try removing the action and method from your form.
From the ng-submit docs
Enables binding angular expressions to onsubmit events.
Additionally it prevents the default action (which for form means sending the request to the server and reloading the current page), but only if the form does not contain action, data-action, or x-action attributes.
So by adding those, you are causing the page to refresh when the form is submitted.
Without them, angular will call $event.preventDefault() for you, which stops the page from being reloaded.
EDIT: Just to add, you were seeing the correct data from the server because you're responding with preset data, which will always be provided when someone posts to /login.
So your form is currently circumventing angular entirely, and directly getting the data from the server.
So after learning a bit of AngularJS I was able to get a controller to call an API and store the results in a variable, which is then displayed on my page (whew...). If I go to:
http://127.0.0.1:3000/#/search
I see the page with the submit form but without the results, and if I go to:
http://127.0.0.1:3000/#/search?query=deep&learning
I see the page with the submit form + the results for the "deep & learning" query. The problem is: I have to enter "?query=deep?learning" manually, I'm unable to use the submit form to get there. I use this code:
<form name='input' action='#search' method='get'>
<div class='input-group'>
<input type='text'
class='form-control'
placeholder='Enter query.'
name='query'>
<div class='input-group-btn'>
<button class='btn btn-default' type='submit'><i class='fa fa-search'></i></button>
</div>
</div>
</form>
With this submit form, if I enter "deep & learning" in the form, I get to
http://127.0.0.1:3000/?query=deep&learning#/search
How do I change my code so entering "deep & learning" would get me to:
http://127.0.0.1:3000/#/search?query=deep&learning
?
Thank you
UPDATE1: code for routes:
var myApp = angular.module('myApp', ['ngRoute'])
.factory('myQuery', ['$http', function($http) {
var doRequest = function(query) {
return $http({
method: 'GET',
url: 'http://127.0.0.1:3000/api/v0/docs?search=' + query
});
};
return {
results: function(query) { return doRequest(query); }
};
}]);
myApp.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
.when('/search', {
templateUrl : 'pages/search.html',
controller : 'searchController'
});
});
myApp.controller('mainController', function($scope) {
// ...
});
myApp.controller('searchController', ['$scope', '$routeParams', 'myQuery', function($scope, $routeParams, myQuery) {
myQuery.results($routeParams.query)
.success(function(data, status, headers) {
$scope.count = data.count;
$scope.results = data.results;
});
}]);
It should simply a matter of changing the action attribute value to get the URL format you want.
In other words:
<form name='input' action='search' method='get'>
Note that the destination URI is no longer prefixed with a hash.
When it is prefixed with a hash as you have it at the moment, it's actually equivalent to directing the submission to the root (i.e. '/') using search as the page anchor.
I'm very new to Angular and am try to make a simple "Hello World" webservice call to a simple Rest web service that I've verified returns "Hello World" when you hit it.
I have 3 alerts in the method. I see the "In method" alert and then don't see any of the other alerts. I've attached fiddler and the web service request is never made. I've got to be overlooking something basic here I would think....any ideas on what am I may be missing?
Fiddler shows that the web service call is successful and I can see the results from the Web Service I expect but using Chrome's developer tools shows me that the call to the service is being cancelled by something inside of Angular.
Thanks in advance to any help provided.
(function () {
var app = angular.module("loginApp", ['ngResource'])
.config(function ($httpProvider) {
// Enable CORS
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
app.controller('LoginController', function ($scope, $http) {
this.loginImage = "images/ActiveView_ContentMgm_140x40.png";
this.loginUser = function () {
var token = "";
var loginUrl = "http://ten1.com/services/rest/demoservice.svc/Login";
delete $http.defaults.headers.common['X-Requested-With'];
var result = $http({ method: 'GET', url: loginUrl, params: { userName: this.userName, passWord: this.passWord } })
.success(function (data, status) {
$scope.status = status;
$scope.data = data;
})
.error(function (data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
token = data.Token;
};
});
})();
UPDATE:
Right now I'm clicking the submit button on a login form and just attempting to get back a string so I can verify basic communication with the web service. My goal is to pass the username/password in and get a token back. Here's the form:
<form ng-submit="loginCtrl.loginUser()" novalidate>
<div class="form-group">
<label for="exampleInputEmail1">Username</label>
<input type="text" class="form-control" style="border-radius:0px" ng-model="loginCtrl.loginForm.userName" placeholder="Enter username">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password </label>
<input type="password" class="form-control" style="border-radius:0px" ng-model="loginCtrl.loginForm.passWord" placeholder="Password">
</div>
<button type="submit" class="btn btn-sm btn-default">Log in</button>
Inject $scope and $http into your controller, not in your loginUser() function:
app.controller('LoginController', function ($scope, $http) {
I found that the service I was hitting was returning a "No 'Access-Control-Allow-Origin' " message which would allow the service to complete but would cause Angular to short circuit. I fixed this by adding an "Access-Control-Allow-Origin" to the Response header in the service.
Links:
Cross Origin Resource Sharing for c# WCF Restful web service hosted as Windows service
"Access-Control-Allow-Origin:*" has no influence in REST Web Service