Today we will be using AngularJS and the great UI Router and the Angular ngAnimate module to create an animated multi-step form. This technique can be used for large forms that you would like to simplify for your users.javascript We can see this technique used in many places on the web. Places like shopping carts, signup forms, onboarding processes, and more have used the multi-step form to ease users through their online forms.css Here’s what we will be building:html Using UI Router and its ability to have nested states and different views per state, we will be able to make a multi-step form fairly easily.java For a quick understanding of the benefits and how UI Router works, check out our other article:AngularJS Routing Using UI-Routergit Let’s get down to business and start creating our awesome form!angularjs |
今天咱們將使用AngularJs和偉大的UI Router以及Angular ngAnimate module建立一個帶動畫的多步表單。這項技術能夠用在你想要簡化用戶操做的大表單上。github 咱們看到這項技術已經應用在了許多的網頁上。好比購物車,註冊表單,入職流程以及許多多步表單,讓用戶更容易在線填寫表單。web 下面咱們將構建它:ajax 使用UI Router,它能內嵌狀態,爲每一個狀態顯示不一樣的view,咱們能讓多步表單變得至關的容易。shell 爲了快速的理解UI Router是怎樣工做的,看咱們的文章:AngularJS使用UI-Router路由 讓咱們言歸正傳,開始建立咱們的最棒的表單! |
Setting Up Our ProjectWe will be using a simple structure for our application. We’ll need a layout file, view files for each part of the form, a stylesheet, and our JavaScript file that will hold all of our Angular code. Here are the files for our application. Go ahead and create these files and we’ll start filling them in as we go. - index.html - form.html - form-profile.html - form-interests.html - form-payment.html - app.js - style.css Each of the form-____.html files will be used as nested views inside of the form. These are what will create each section of our form. |
譯者信息![]() 建立工程建立工程有個模板結構. 須要個 佈局文件 , 每一個表單的視圖文件, 格式文件, 以及JavaScript 文件. 下面就是文件清單,先建立好它們,接着在填充內容 - index.html - form.html - form-profile.html - form-interests.html - form-payment.html - app.js - style.css
每一個表單-____.html表示層級結構中的html文件. 這些結構最終建立咱們的表單結構. |
Our Layout/Template File index.htmlLet’s start our project by creating the main file that will bring all of our resources together into one place. We will use our Here we will, load all our resources (AngularJS, ngAnimate, UI Router, our script and stylesheet) and place a <!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- CSS --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/darkly/bootstrap.min.css"> <link rel="stylesheet" href="style.css"> <!-- JS --> <!-- load angular, nganimate, and ui-router --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-animate.min.js"></script> <script src="app.js"></script> </head> <!-- apply our angular app --> <body ng-app="formApp"> <div class="container"> <!-- views will be injected here --> <div ui-view></div> </div> </body> </html> With all of our files loaded, let’s go into our |
譯者信息![]() 咱們的佈局/模板文件 index.html 咱們經過創建一個主文件來引入咱們所須要的全部資源以開始咱們的項目 ,這裏咱們使用 index.html 文件做爲主文件 如今,咱們加載咱們所需的資源(AngularJS, ngAnimate, Ui Router, 以及其餘腳本和樣式表)而且設定一個 ui-view用來告知 UI Router 咱們的視圖須要顯示到哪裏。這裏咱們使用 Bootstrap 來快速應用樣式。 <!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- CSS --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/darkly/bootstrap.min.css"> <link rel="stylesheet" href="style.css"> <!-- JS --> <!-- load angular, nganimate, and ui-router --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-animate.min.js"></script> <script src="app.js"></script> </head> <!-- apply our angular app --> <body ng-app="formApp"> <div class="container"> <!-- views will be injected here --> <div ui-view></div> </div> </body> </html> 完成全部文件的引入後,讓咱們進入 app.js 開始建立Angular應用和最基本的路由配置。 注意咱們是如何把Angular App (formApp) 應用到 body 上面的。 |
Building Our Angular App app.jsWe will create our application and routes. For larger applications, you’ll want to separate your Angular application, routes, and controllers into their own separate modules, but for our purposes, we’ll place them all together as a happy family in // app.js // create our angular app and inject ngAnimate and ui-router // ============================================================================= angular.module('formApp', ['ngAnimate', 'ui.router']) // configuring our routes // ============================================================================= .config(function($stateProvider, $urlRouterProvider) { $stateProvider // route to show our basic form (/form) .state('form', { url: '/form', templateUrl: 'form.html', controller: 'formController' }) // nested states // each of these sections will have their own view // url will be nested (/form/profile) .state('form.profile', { url: '/profile', templateUrl: 'form-profile.html' }) // url will be /form/interests .state('form.interests', { url: '/interests', templateUrl: 'form-interests.html' }) // url will be /form/payment .state('form.payment', { url: '/payment', templateUrl: 'form-payment.html' }); // catch all route // send users to the form page $urlRouterProvider.otherwise('/form/profile'); }) // our controller for the form // ============================================================================= .controller('formController', function($scope) { // we will store all of our form data in this object $scope.formData = {}; // function to process the form $scope.processForm = function() { alert('awesome!'); }; }); We now have our application with
We’ll demonstrate this in our next section. We now have to create the view for our form and each of its nested states. |
譯者信息![]() 建立咱們的Angular App app.js如今咱們來建立應用和路由。 在一個大型應用中, 你確定但願把你的Angular應用、路由、控制器分佈到它們各自的模塊中,可是爲了完成咱們的簡單用例,咱們將把它們都放到app.js這個歡樂的你們庭中。 // app.js // create our angular app and inject ngAnimate and ui-router // ============================================================================= angular.module('formApp', ['ngAnimate', 'ui.router']) // configuring our routes // ============================================================================= .config(function($stateProvider, $urlRouterProvider) { $stateProvider // route to show our basic form (/form) .state('form', { url: '/form', templateUrl: 'form.html', controller: 'formController' }) // nested states // each of these sections will have their own view // url will be nested (/form/profile) .state('form.profile', { url: '/profile', templateUrl: 'form-profile.html' }) // url will be /form/interests .state('form.interests', { url: '/interests', templateUrl: 'form-interests.html' }) // url will be /form/payment .state('form.payment', { url: '/payment', templateUrl: 'form-payment.html' }); // catch all route // send users to the form page $urlRouterProvider.otherwise('/form/profile'); }) // our controller for the form // ============================================================================= .controller('formController', function($scope) { // we will store all of our form data in this object $scope.formData = {}; // function to process the form $scope.processForm = function() { alert('awesome!'); }; });
如今咱們擁有了一個已經注入了ngAnimate和ui.router的應用。 咱們一樣也創建了相應的路由。注意咱們是如何爲每個視圖區域定義 url,視圖文件(templateUrl) 和 控制器的。 form 將是咱們的主視圖區域。它一樣有一個以 . 分割的子視圖區域 form.profile。這種想法能實如今應用狀態發生變化時(譯者:多是路由、queryString等),子視圖將會在主視圖區域中顯示出來。(譯者:並且能夠做到僅更新子視圖區域變化,記錄子視圖區域狀態)。 咱們將在下一節中進行演示。 如今咱們須要爲form以及它的子視圖區域建立視圖。 |
Form Template View form.htmlLet’s start by creating our main form.html file. This will be used as a template file for the rest of our form view files just like our <!-- form.html --> <div class="row"> <div class="col-sm-8 col-sm-offset-2"> <div id="form-container"> <div class="page-header text-center"> <h2>Let's Be Friends</h2> <!-- the links to our nested states using relative paths --> <!-- add the active class if the state matches our ui-sref --> <div id="status-buttons" class="text-center"> <a ui-sref-active="active" ui-sref=".profile"><span>1</span> Profile</a> <a ui-sref-active="active" ui-sref=".interests"><span>2</span> Interests</a> <a ui-sref-active="active" ui-sref=".payment"><span>3</span> Payment</a> </div> </div> <!-- use ng-submit to catch the form submission and use our Angular function --> <form id="signup-form" ng-submit="processForm()"> <!-- our nested state views will be injected here --> <div id="form-views" ui-view></div> </form> </div> <!-- show our formData as it is being typed --> <pre> {{ formData }} </pre> </div> </div> Notice how this is the second time we’ve used Adding Active Classes Based on State We will want each of our status buttons to be able to show if they are active. In order to do this, we will use To add validation to your form, also read: AngularJS Form Validation By now you’re probably wondering what our form looks like. Let’s go into our browser and take a look! Getting there. Not really everything we had hoped for, but it has the beginnings of something great. Let’s keep pushing forward. Let’s add a bit of stylilng and then we’ll add our nested views and animations. |
譯者信息![]() 表單模板視圖 form.html讓咱們重新建form.html開始。這個文件將會在咱們剩下的表單視圖文件中充當模板的做用,正如index.html被用做整個項目的整體模板同樣。咱們所要做的是在該文件中包含ui-view,這樣可使嵌套聲明知道該在何處注入他們的視圖。 <!-- form.html --> <div class="row"> <div class="col-sm-8 col-sm-offset-2"> <div id="form-container"> <div class="page-header text-center"> <h2>Let's Be Friends</h2> <!-- the links to our nested states using relative paths --> <!-- add the active class if the state matches our ui-sref --> <div id="status-buttons" class="text-center"> <a ui-sref-active="active" ui-sref=".profile"><span>1</span> Profile</a> <a ui-sref-active="active" ui-sref=".interests"><span>2</span> Interests</a> <a ui-sref-active="active" ui-sref=".payment"><span>3</span> Payment</a> </div> </div> <!-- use ng-submit to catch the form submission and use our Angular function --> <form id="signup-form" ng-submit="processForm()"> <!-- our nested state views will be injected here --> <div id="form-views" ui-view></div> </form> </div> <!-- show our formData as it is being typed --> <pre> {{ formData }} </pre> </div> </div> 注意咱們是如何第二次在項目中使用ui-view的。這就是UI Router偉大的地方:咱們能夠嵌套聲明和視圖。這可以在咱們開發應用時提供給咱們很是多的靈活性。關於UI Router視圖的內容,請參見 官方文檔。 添加基於狀態的激活類 咱們但願每個狀態按鈕可以在他們被激活時展現。爲了達到這個效果,咱們將會使用UI Router提供的ui-sref-active。若是ui-sref和當前狀態一致,則會添加咱們指定的類。 爲了給本身的表單添加驗證,請參見AngularJS表單驗證。 如今,你可能想知道咱們的表單究竟看起來是什麼樣子。讓咱們打開瀏覽器看一眼。 目前爲止,咱們並無徹底按照但願的那樣獲得全部的內容,可是這是一系列偉大事情的開端。讓咱們繼續前進,添加一點樣式,以後會添加一些嵌入視圖和註釋。 |
Basic Styling style.cssWe are going to style our /* style.css */ /* BASIC STYLINGS ============================================================================= */ body { padding-top:20px; } /* form styling */ #form-container { background:#2f2f2f; margin-bottom:20px; border-radius:5px; } #form-container .page-header { background:#151515; margin:0; padding:30px; border-top-left-radius:5px; border-top-right-radius:5px; } /* numbered buttons */ #status-buttons { } #status-buttons a { color:#FFF; display:inline-block; font-size:12px; margin-right:10px; text-align:center; text-transform:uppercase; } #status-buttons a:hover { text-decoration:none; } /* we will style the span as the circled number */ #status-buttons span { background:#080808; display:block; height:30px; margin:0 auto 10px; padding-top:5px; width:30px; border-radius:50%; } /* active buttons turn light green-blue*/ #status-buttons a.active span { background:#00BC8C; } Now our buttons will look better and be more in line with what we want. Let’s move on to the nested views. Nested Form Views form-profile.html, form-interests.html, form-payment.htmlThis will be the easy part. We’ll define our different views with the input fields that we need. We’ll also bind them to our Here are our view files that are used in our nested states: Form Profile View<!-- form-profile.html --> <div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" name="name" ng-model="formData.name"> </div> <div class="form-group"> <label for="email">Email</label> <input type="text" class="form-control" name="email" ng-model="formData.email"> </div> <div class="form-group row"> <div class="col-xs-6 col-xs-offset-3"> <a ui-sref="form.interests" class="btn btn-block btn-info"> Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span> </a> </div> </div> Form Interests View<!-- form-interests.html --> <label>What's Your Console of Choice?</label> <div class="form-group"> <div class="radio"> <label> <input type="radio" ng-model="formData.type" value="xbox" checked> I like XBOX </label> </div> <div class="radio"> <label> <input type="radio" ng-model="formData.type" value="ps"> I like PS4 </label> </div> </div> <div class="form-group row"> <div class="col-xs-6 col-xs-offset-3"> <a ui-sref="form.payment" class="btn btn-block btn-info"> Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span> </a> </div> </div> Form Payment View<!-- form-payment.html --> <div class="text-center"> <span class="glyphicon glyphicon-heart"></span> <h3>Thanks For Your Money!</h3> <button type="submit" class="btn btn-danger">Submit</button> </div> Now that we have, defined these views, they will show up when we view our form. We also link to the each new state using the next button and |
譯者信息![]() 基礎Stylingstyle.css咱們將設計咱們的form-container和status-buttons來是咱們的表單看起來更好。 /* style.css */ /* BASIC STYLINGS ============================================================================= */ body { padding-top:20px; } /* form styling */ #form-container { background:#2f2f2f; margin-bottom:20px; border-radius:5px; } #form-container .page-header { background:#151515; margin:0; padding:30px; border-top-left-radius:5px; border-top-right-radius:5px; } /* numbered buttons */ #status-buttons { } #status-buttons a { color:#FFF; display:inline-block; font-size:12px; margin-right:10px; text-align:center; text-transform:uppercase; } #status-buttons a:hover { text-decoration:none; } /* we will style the span as the circled number */ #status-buttons span { background:#080808; display:block; height:30px; margin:0 auto 10px; padding-top:5px; width:30px; border-radius:50%; } /* active buttons turn light green-blue*/ #status-buttons a.active span { background:#00BC8C; }
如今咱們的按鈕更好看了而且更符合咱們想要的了,接下來咱們看下嵌套視圖。 嵌套視圖form-profile.html, form-interests.html, form-payment.html這部分會比較簡單。咱們將定義不一樣的帶有咱們須要的輸入框的視圖。而且將他們綁定到formData對象以便咱們能看到輸入的數據。 下面是咱們用於嵌套視圖的視圖文件: 表單概要視圖<!-- form-profile.html --> <div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" name="name" ng-model="formData.name"> </div> <div class="form-group"> <label for="email">Email</label> <input type="text" class="form-control" name="email" ng-model="formData.email"> </div> <div class="form-group row"> <div class="col-xs-6 col-xs-offset-3"> <a ui-sref="form.interests" class="btn btn-block btn-info"> Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span> </a> </div> </div>
表單興趣視圖<!-- form-interests.html --> <label>What's Your Console of Choice?</label> <div class="form-group"> <div class="radio"> <label> <input type="radio" ng-model="formData.type" value="xbox" checked> I like XBOX </label> </div> <div class="radio"> <label> <input type="radio" ng-model="formData.type" value="ps"> I like PS4 </label> </div> </div> <div class="form-group row"> <div class="col-xs-6 col-xs-offset-3"> <a ui-sref="form.payment" class="btn btn-block btn-info"> Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span> </a> </div> </div>
表單支付視圖<!-- form-payment.html --> <div class="text-center"> <span class="glyphicon glyphicon-heart"></span> <h3>Thanks For Your Money!</h3> <button type="submit" class="btn btn-danger">Submit</button> </div>
既然咱們已經定義了這些視圖,那麼當咱們瀏覽表單時,他們就會顯示出來。一樣咱們用下一個按鈕和ui-sref來鏈接每個新視圖. |
When using Here is each page of our form now. With our pages out of the way, let’s add in our animations. |
譯者信息![]() 當使用ui-sref時,你要鏈接到你路由中定義的state而不是URL。而後Angular會使用這個來爲你構建href。 下面是咱們表單目前的每個頁面。 爲了讓咱們的頁面不一樣尋常,讓咱們加上動畫效果。 |
Animating Our FormSince we already loaded All we have to do now is style those and we have our finalized form! To understand Angular animations,this article is a good getting started point. Let’s jump into our CSS file, add our animations, and apply them to our form. /* style.css */ /* ANIMATION STYLINGS ============================================================================= */ #signup-form { position:relative; min-height:300px; overflow:hidden; padding:30px; } #form-views { width:auto; } /* basic styling for entering and leaving */ /* left and right added to ensure full width */ #form-views.ng-enter, #form-views.ng-leave { position:absolute; left:30px; right:30px; transition:0.5s all ease; -moz-transition:0.5s all ease; -webkit-transition:0.5s all ease; } /* enter animation */ #form-views.ng-enter { -webkit-animation:slideInRight 0.5s both ease; -moz-animation:slideInRight 0.5s both ease; animation:slideInRight 0.5s both ease; } /* leave animation */ #form-views.ng-leave { -webkit-animation:slideOutLeft 0.5s both ease; -moz-animation:slideOutLeft 0.5s both ease; animation:slideOutLeft 0.5s both ease; } /* ANIMATIONS ============================================================================= */ /* slide out to the left */ @keyframes slideOutLeft { to { transform: translateX(-200%); } } @-moz-keyframes slideOutLeft { to { -moz-transform: translateX(-200%); } } @-webkit-keyframes slideOutLeft { to { -webkit-transform: translateX(-200%); } } /* slide in from the right */ @keyframes slideInRight { from { transform:translateX(200%); } to { transform: translateX(0); } } @-moz-keyframes slideInRight { from { -moz-transform:translateX(200%); } to { -moz-transform: translateX(0); } } @-webkit-keyframes slideInRight { from { -webkit-transform:translateX(200%); } to { -webkit-transform: translateX(0); } } First, we style our form so that when a view leaves or enters, they are positioned absolutely. This ensures that one view doesn’t push the other view down when entering. Second, we apply our animations to the Third, we define the animations using @keyframes. With all those parts working together, we have our full form that has Angular animations, UI Router based states, and Angular data-binding. |
譯者信息![]() 讓咱們的表單產生動畫效果由於在項目開始的時候,咱們已經加載了ngAnimate,它已經添加到須要動畫的的類上了。當視圖進入或退出的時候,它將自動添加類ng-enter和ng-leave。 如今咱們全部作的就是經過樣式造成咱們最終的表單。爲了理解Angular動畫,這篇文章是一個很好的起點。 讓咱們進去css文件,將動畫,並應用到咱們的表單上 /* style.css */ /* ANIMATION STYLINGS ============================================================================= */ #signup-form { position:relative; min-height:300px; overflow:hidden; padding:30px; } #form-views { width:auto; } /* basic styling for entering and leaving */ /* left and right added to ensure full width */ #form-views.ng-enter, #form-views.ng-leave { position:absolute; left:30px; right:30px; transition:0.5s all ease; -moz-transition:0.5s all ease; -webkit-transition:0.5s all ease; } /* enter animation */ #form-views.ng-enter { -webkit-animation:slideInRight 0.5s both ease; -moz-animation:slideInRight 0.5s both ease; animation:slideInRight 0.5s both ease; } /* leave animation */ #form-views.ng-leave { -webkit-animation:slideOutLeft 0.5s both ease; -moz-animation:slideOutLeft 0.5s both ease; animation:slideOutLeft 0.5s both ease; } /* ANIMATIONS ============================================================================= */ /* slide out to the left */ @keyframes slideOutLeft { to { transform: translateX(-200%); } } @-moz-keyframes slideOutLeft { to { -moz-transform: translateX(-200%); } } @-webkit-keyframes slideOutLeft { to { -webkit-transform: translateX(-200%); } } /* slide in from the right */ @keyframes slideInRight { from { transform:translateX(200%); } to { transform: translateX(0); } } @-moz-keyframes slideInRight { from { -moz-transform:translateX(200%); } to { -moz-transform: translateX(0); } } @-webkit-keyframes slideInRight { from { -webkit-transform:translateX(200%); } to { -webkit-transform: translateX(0); } } 首先,肯定視圖離開或進去時,表單的樣式,他們是絕對定位的。須要確認當視圖進入的時候一個視圖不會放到另外一個視圖的下面。 其次,應用咱們的動畫到.ng-enter和.ng-leave類 第三,用@keyframes定義動畫。全部這些部分組合到一塊兒,咱們的表單就有了Angular動畫,基於狀態的UI Router和Angular數據綁定。 |
ConclusionThere are many great ways that UI-Router, ngAnimate, and all the fun stuff in Angular can come together to create great applications. Hopefully this article has shown you how you can take a multi-step form and use many Angular techniques and tools to build it. These concepts here can be applied to many other user interfaces, especially when being creative and letting your imagination run wild. Thanks for reading and as always, sound off in the comments with any questions. |
譯者信息![]() 結論UI-Router, ngAnimate, 和其餘不少有趣的 Angular功能會建立出不少很棒的應用 但願本文能展現給你一些建立Angular應用的小技巧和編譯的工具使用方法 t. 這些概念也能引伸到其餘用戶界面設計方面, 尤爲在發揮你的創造性方面提供指引.感謝你花時間閱讀本文,若有疑問歡迎指正. |