در قسمت قبلی این سری مقاله ها بحث لاراول رو کامل کردیم اینبار میخواهیم بیشتر درمورد نقش Angular در پروژه مون صحبت کنیم. لینک دریافت پروژه
نصب Angular Seed
بیایید با اسکلت بندی بخش client side کار شروع کنیم, برای این کار از angular seed استفاده می کنیم.
ابتدا باید پروژه رو از git دریافت کنید :
git clone https://github.com/angular/angular-seed.git
cd angular-seed
حالا باید وابستگیهای angular-seed رو دریافت کنیم. برای این کار :
npm install
بعد از انجام اینکار فولدر node_modules و app/bower_components رو در مسیر اصلی پروژه می بینید.
هم لاراول 5 و هم Angularjs بصورت پیشفرض از پورت 8000 استفاده میکنند پس ما باید یک پورت دیگه برای یکیشون درنظر بگیریم. بیایید پورت پروژه angular-seed رو عوض کنیم.
فایل package.json باز کرده و تغییر زیر اعمال کنید :
"start": "http-server -a localhost -p 8080 -c-1"
حالا پروژه رو اجرا کنید :
npm start
حالا به مسیر زیر بروید :
http://localhost:8080/app/index.html
نصب ui-router
پروژه Angular Seed بصورت پیشفرض از router خود angular استفاده می کنه. اما من ui-router رو پیشنهاد میدم. پس ما پروژه خودمون رو به صورت زیر تغییر میدیم. ابتدا اون رو دانلود میکنیم :
bower install angular-ui-router –save
در فایل index.html اضافش میکنیم :
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
حالا ui-router رو به app.js بیافزایید :
angular.module('myApp', [
// 'ngRoute',
'ui.router',
'myApp.view1',
'myApp.view2'
'myApp.version'
])
ساخت مسیرهای جدید
دو مسیر میسازیم یکی برای auth و دیگری برای jokes. حالا یک مسیر جدید در پوشه app به نام view_auth و view_jokes بسازید. ساختار دایرکتوری به شکل زیر درمیاد :
فایل view_auth/auth.js باز کرده و به شکل زیر آپدیت کنید :
angular.module('myApp.auth', [])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('auth', {
url: '/auth',
views: {
'jokesContent': {
templateUrl: "view_auth/auth.html",
controller: 'AuthCtrl as auth'
}
}
})
}])
.controller('AuthCtrl', ['$rootScope', function($rootScope){
}])
حالا فایل view_jokes/jokes.js رو باز کرده و آپدیت کنید :
angular.module('myApp.jokes', [])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('jokes', {
url: '/jokes',
views: {
'jokesContent': {
templateUrl: "view_jokes/jokes.html",
controller: 'JokesCtrl as jokes'
}
}
})
}])
.controller('JokesCtrl', ['$rootScope', function($rootScope){
}])
فایلهای view_auth/auth.html و view_jokes/jokes.html باز کرده و یکسری محتوا اضافه کنید.
و فایلهای اسکریپت رو به index.html اضافه کنید :
<script src="view_auth/auth.js"></script>
<script src="view_jokes/jokes.js"></script>
حالا وابستگیهای app.js رو به روز کنید :
// Declare app level module which depends on views, and components
angular.module('myApp', [
// 'ngRoute',
'ui.router',
'myApp.jokes',
'myApp.view2',
'myApp.auth',
'myApp.version'
])
میتونید مسیرها رو در مرورگر مشاهده کنید :
http://localhost:8080/app/#/auth
,
http://localhost:8080/app/#/jokes
تأیید اعتبار Clinet Side
فایل view_auth/auth.html رو باز کرده و کد زیر رو بیافزایید :
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading"> <strong class="">Login</strong>
</div>
<div class="panel-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">Email</label>
<div class="col-sm-9">
<input type="email" class="form-control" id="inputEmail3" placeholder="Email" required="" ng-model="auth.email">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">Password</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="inputPassword3" placeholder="Password" required="" ng-model="auth.password">
</div>
</div>
<div class="form-group last">
<div class="col-sm-offset-3 col-sm-9">
<button type="submit" class="btn btn-success btn-sm" ng-click="auth.login()">Sign in</button>
<button type="reset" class="btn btn-default btn-sm">Reset</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
خروجی به صورت زیر میشود :
استفاده از Satellizer
حالا برای تأیید اعتبار client side ما از یک سیستم token base به نام satellizer استفاده می کنیم.
bower install satellizer –save
فایل satellizer.js رو به index.html اضافه کنید :
<script src="bower_components/satellizer/satellizer.js"></script>
اون رو به لیست وابستگیهای app.js اضافه کنید :
angular.module('myApp', [
// 'ngRoute',
'ui.router',
'myApp.jokes',
'myApp.view2',
'myApp.auth',
'myApp.version',
'satellizer'
])
و کانفیگ login رو در app.js وارد کنید :
.config(['$stateProvider', '$urlRouterProvider', '$authProvider', function($stateProvider, $urlRouterProvider, $authProvider) {
$authProvider.loginUrl = 'http://localhost:8000/api/v1/authenticate';
// $urlRouterProvider.otherwise('/view1');
$urlRouterProvider.otherwise('/auth');
}]);
این کتابخانه به شما دسترسی به authProvider$ میده. ما میدونیم که برای api لاراول هربار نیاز به توکن داریم این کتابخانه به ما اطمینان میده با هر درخواست توکن هم بصورت خودکار فرستاده بشه.
فایل view_auth/auth.js رو باز کرده و کنترلر رو به شکل زیر تغییر بدید :
.controller('AuthCtrl', ['$auth', '$state', '$http', '$rootScope', function($auth, $state, $http, $rootScope) {
var vm = this;
vm.loginError = false;
vm.loginErrorText;
vm.login = function() {
var credentials = {
email: vm.email,
password: vm.password
}
$auth.login(credentials).then(function() {
$http.get('http://localhost:8000/api/v1/authenticate/user').success(function(response){
var user = JSON.stringify(response.user);
localStorage.setItem('user', user);
$rootScope.currentUser = response.user;
$state.go('jokes');
})
.error(function(){
vm.loginError = true;
vm.loginErrorText = error.data.error;
console.log(vm.loginErrorText);
})
});
}
حالا بعد از شروع سرور لاراول مسیر auth باز کنید و بعد از وارد کردن اطلاعات کاربری دکمه ثبت رو بزنید. شما آیتم های زیر رو میبینید که به حافظه محلی اضافه شده :
دریافت تمام جوک ها
فایل view_jokes/jokes.html باز کنید و بصورت زیر تغییر بدید :
<div class="col-sm-6 col-sm-offset-3">
<div>
<ul class="list-group">
<li class="list-group-item" ng-repeat="joke in jokes.jokes">
<h5>{{joke.joke}}</h5>
<h5>{{joke.submitted_by}}</h5>
</li>
</ul>
<div class="alert alert-danger" ng-if="jokes.error">
<strong>There was an error: </strong> {{jokes.error}}
<br>Please go back and login again...
</div>
</div>
</div>
حالا view_jokes/jokes.js باز کنید و بصورت زیر دربیارید :
.controller('JokesCtrl', ['$http', '$auth', '$rootScope','$state', '$q' , function($http, $auth, $rootScope, $state, $q) {
var vm = this;
vm.jokes = [];
vm.error;
vm.joke;
$http.get('http://localhost:8000/api/v1/jokes').success(function(jokes){
console.log(jokes);
vm.jokes = jokes.data;
}).error(function(error){
vm.error = error;
})
vm.init();
}]);
من میتونم بخش زیادی از کد رو به factory یا service ببرم اما برای راحتی کار این رو انجام نمیدم.
حالا اگر مسیر jokes رو باز کنید :
آراستن اپلیکیشن و بخش خروج از حساب
فایل index.html باز کرده و کد container رو آپدیت کنید :
<div class="container">
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="">Jokes App</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a ui-sref="auth">Auth</a></li>
<li><a ui-sref="jokes">Jokes</a></li>
</ul>
<ul class="nav navbar-nav navbar-right" ng-show="currentUser != null">
<li><a href="">Welcome, {{currentUser.name}}</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">My Profile <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a ng-click="logout()" style="cursor: pointer;">Logout</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div ui-view="jokesContent"></div>
</div>
حالا فایل app.js رو باز کرده و کد logout رو اضافه کنید :
.run(function ($rootScope, $state, $auth) {
$rootScope.logout = function() {
$auth.logout().then(function() {
localStorage.removeItem('user');
$rootScope.currentUser = null;
$state.go('auth');
});
}
})
$rootScope.currentUser = JSON.parse(localStorage.getItem('user'));
}
حالا logout – خروج از حساب – کار می کنه.
امن سازی مسیرها
هماکنون اگر کسی تأیید هویت شده باشه هنوز به مسیر auth دسترسی داره برای جلوگیری از این باگ ها از پکیج angular-permission بهره می بریم.
bower install angular-permission –save
آپدیت app.js
angular.module('myApp', [
// 'ngRoute',
'ui.router',
'myApp.jokes',
'myApp.view2',
'myApp.auth',
'myApp.version',
'satellizer',
'permission'
])
کانفیگ فایل view_auth/auth.js :
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('auth', {
url: '/auth',
data: {
permissions: {
except: ['isloggedin'],
redirectTo: 'jokes'
}
},
views: {
'jokesContent': {
templateUrl: "view_auth/auth.html",
controller: 'AuthCtrl as auth'
}
}
})
}])
با استفاده از نقش isloggedin این مسیر برای کاربران وارد نشده قابل دسترس میشه.
برای تعریف نقش در run function - app.js :
Permission
.defineRole('isloggedin', function (stateParams) {
// If the returned value is *truthy* then the user has the role, otherwise they don't
// console.log("isloggedin ", $auth.isAuthenticated());
if ($auth.isAuthenticated()) {
return true; // Is loggedin
}
return false;
})
فایل view_jokes/jokes.js :
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('jokes', {
url: '/jokes',
data: {
permissions: {
except: ['anonymous'],
redirectTo: 'auth'
}
},
views: {
'jokesContent': {
templateUrl: "view_jokes/jokes.html",
controller: 'JokesCtrl as jokes'
}
}
})
}])
و تعریف نقش افراد ناشناس در app.js run function :
// Define anonymous role
Permission
.defineRole('anonymous', function (stateParams) {
// If the returned value is *truthy* then the user has the role, otherwise they don't
// var User = JSON.parse(localStorage.getItem('user'));
// console.log("anonymous ", $auth.isAuthenticated());
if (!$auth.isAuthenticated()) {
return true; // Is anonymous
}
return false;
})
.defineRole('isloggedin', function (stateParams) {
// If the returned value is *truthy* then the user has the role, otherwise they don't
// console.log("isloggedin ", $auth.isAuthenticated());
if ($auth.isAuthenticated()) {
return true; // Is loggedin
}
return false;
})
;
درخواست های POST, UPDATE, DELETE
فایل view_jokes/jokes.html :
<div class="col-sm-6 col-sm-offset-3">
<div class="row">
<div class="col-sm-12">
<div class="input-group">
<input type="text" class="form-control" placeholder="Add new joke.." ng-model="jokes.joke">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="jokes.addJoke()">Add!</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div>
<br>
<div>
<ul class="list-group">
<li class="list-group-item" ng-repeat="joke in jokes.jokes">
<span ng-hide="editEnabled">
{{joke.joke}}
<a href="#" ng-click="editEnabled=!editEnabled"><span class="glyphicon glyphicon-pencil" ></span></a>
</span>
<span ng-show="editEnabled">
<input ng-model="joke.joke">
<a href="#" ng-click="editEnabled=!editEnabled; jokes.updateJoke(joke)"><span class="glyphicon glyphicon-ok" ></span></a>
</span>
<!-- <h4>{{joke.joke}}</h4> -->
<span style="cursor: pointer;" class="glyphicon glyphicon-trash" ng-click="jokes.deleteJoke($index, joke.joke_id)"></span>
<h5>{{joke.submitted_by}}</h5>
</li>
</ul>
<div class="alert alert-danger" ng-if="jokes.error">
<strong>There was an error: </strong> {{jokes.error}}
<br>Please go back and login again...
</div>
</div>
</div>
و فایل view_jokes/jokes.js :
.controller('JokesCtrl', ['$http', '$auth', '$rootScope','$state', '$q' , function($http, $auth, $rootScope, $state, $q) {
var vm = this;
vm.jokes = [];
vm.error;
vm.joke;
$http.get('http://localhost:8000/api/v1/jokes').success(function(jokes){
console.log(jokes);
vm.jokes = jokes.data;
}).error(function(error){
vm.error = error;
})
vm.addJoke = function() {
$http.post('http://localhost:8000/api/v1/jokes', {
body: vm.joke,
user_id: $rootScope.currentUser.id
}).success(function(response) {
// console.log(vm.jokes);
// vm.jokes.push(response.data);
vm.jokes.unshift(response.data);
console.log(vm.jokes);
vm.joke = '';
// alert(data.message);
// alert("Joke Created Successfully");
}).error(function(){
console.log("error");
});
};
vm.updateJoke = function(joke){
console.log(joke);
$http.put('http://localhost:8000/api/v1/jokes/' + joke.joke_id, {
body: joke.joke,
user_id: $rootScope.currentUser.id
}).success(function(response) {
// alert("Joke Updated Successfully");
}).error(function(){
console.log("error");
});
}
vm.deleteJoke = function(index, jokeId){
console.log(index, jokeId);
$http.delete('http://localhost:8000/api/v1/jokes/' + jokeId)
.success(function() {
vm.jokes.splice(index, 1);
});;
}
}]);
میتونید عملیات های ADD, UPDATE, DELETE رو به راحتی انجام بدید.
صفحه بندی
ما میخواهیم یک دکمه بارگزاری بیشتر قرار بدیم. این دکمه رو در view_jokes/jokes.html :
<button class="btn btn-success" ng-click="jokes.loadMore()" style="float:right">Load More....</button>
فایل view_jokes/jokes.js :
// $http.get('http://localhost:8000/api/v1/jokes').success(function(jokes){
// console.log(jokes);
// vm.jokes = jokes.data;
// }).error(function(error){
// vm.error = error;
// })
vm.lastpage=1;
vm.init = function() {
vm.lastpage=1;
$http({
url: 'http://localhost:8000/api/v1/jokes',
method: "GET",
params: {page: vm.lastpage}
}).success(function(jokes, status, headers, config) {
vm.jokes = jokes.data;
vm.currentpage = jokes.current_page;
});
};
vm.init();
vm.loadMore = function() {
vm.lastpage +=1;
$http({
url: 'http://localhost:8000/api/v1/jokes',
method: "GET",
params: {page: vm.lastpage}
}).success(function (jokes, status, headers, config) {
vm.jokes = vm.jokes.concat(jokes.data);
});
};
حالا بیایید کد رو تست کنیم :
تبریک میگم api لاراول شما به همراه client side با تکنولوژی AngularJS تکمیل شد!
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید