UNPKG

kickstrap

Version:

Framework for advanced Bootstrap web development

209 lines (207 loc) 9.43 kB
.page-header h1 Creating Angular Templates p.lead This page is mean to be a short primer on Angular. See a(href="http://angularjs.org/") Angular's official site for more instruction. p You may have noticed a lot of the action on pages such as the shopping cart happen very quickly. p This is accomplished by using Angular to em bind | the UI. This document will show you examples of how this is done and includes a tutorial to create a new Angular-bound page from scratch. h2 Binding data in the products page p Looking at products.jade, the most important part for Angular is the definition of the Angular Controller that binds the page. That's right here: p pre .container(ng-controller='ProductsCtrl') p Everything nested below this is bound by the Products Controller. Let's look at that. Open apps/ang-app/controllers/products.coffee. p pre define ['./module'], (controllers) -> | controllers.controller 'ProductsCtrl', ['$scope', '$firebase', 'ngProgress', ($scope, $firebase, ngProgress) -> | ... | ] p You may notice a few things ol li The file asks for "module" to be loaded ul li This is to load a helper file to insure Angular loads first and gets our "controllers" module reader for extending. li 'ProductsCtrl' is named ul li This is the keyword that will link this controller to the HTML side. This keyword must be spelled exactly the same in both places. li $scope, $firebase, ngProgress are repeated ul li This is a trick Angular uses to prevent minification of the JavaScript file from breaking the references to these resources. p Let's try a hello world experiment. Add this anywhere denoted by the ellipsis (...) above. p pre $scope.test = 'Hello world' p code $scope | is used very often in Angular code, and just tells Angular we can use this in the template and it should automatically watch the variable we create for any changes. p Now open products.jade and add a line under "Get them before they're gone" which references "$scope.test" In the Jade file, we don't have to say "$scope," because only $scoped variables can be used anyway. p pre(ng-non-bindable) h1 On Sale Now | p.lead Get them before they're gone | p {{test}} p Notice, we don't have to say "$scope" as it is implied. p You should now see "Hello world" appear under the subtitle. h3 Showing loops p How did we create the list of products on the left? This is done by defining a $scoped variable that is an array, and repeating through it in the jade template. Look for the HTML attribute code ng-repeat | in the Jade file. It should say something like this: p pre div(ng-repeat="product in products") p This is looking for an array called products. Each item in the array of products will be given the name "product" without an "s". "product" is now a $scoped variable we can refer to. In products, we use code(ng-non-bindable) {{product.name}} | under the code ng-repeat | and this is repeated for the length of code $scope.products. p Notice, we used code(ng-non-bindable) {{product.name}} | and not code(ng-non-bindable) {{product}} | . This is because each item in the code $scope.products | array is actually an object with a "name" definition. p pre(ng-non-bindable) div(ng-repeat="product in products") {{product.name}} h2 Create a new Angular-bound page p For a new Angular page, we'll need at least two parts: The Jade file to display it, and the JS controller to bind it. p For this example, we'll create a page that lists names and gives us an input box to filter through them. You'll be surprised how simple this is. h3 Create the HTML p Create a page in views called "customers.jade" with the following content: p pre extends layout |   | block variables | - var active = 'customers' |   | block content | include _header p This starts our page out by loading all the necessary resources we load on the other pages, including our navigation header in the _header.jade partial. We're also declaring the "active" variable as "customers" to tell the header it should darken this menu item when we're on this page. p We also need to tell our _header.jade partial to look for this variable. Open views/_header.jade and look for this line: p pre each menuItem in [{title:'Home', url: '/', slug:'home'}, {title: 'Docs', url: '/docs.html#first-steps', slug: 'docs'}, {title: 'Products', url: '/products.html', slug: 'products'}, {title: 'New Page', url: '/newpage.html#disqus_thread', slug: 'newpage'}] p We need to add our customers page to this list. p pre each menuItem in [{title:'Home', url: '/', slug:'home'}, {title: 'Docs', url: '/docs.html#first-steps', slug: 'docs'}, {title: 'Products', url: '/products.html', slug: 'products'}, {title: 'New Page', url: '/newpage.html#disqus_thread', slug: 'newpage'}, {title: 'Customers', url: '/customers.html', slug: 'customers'}] p We've just told _header to add our customers link to the loop and listen for the page to declare the code active | variable as "customers" in order to give that menu's code li | the code active | class. p Now let's keep going: p pre(ng-non-bindable) block content | include _header |   | h1 Customers | div(ng-controller="CustomersCtrl") | input(type="text", ng-model="customerFilter") | ul | li(ng-repeat="customer in customers") {{customer.name}} p .alert.alert-info Notice, if you make customers from a firebase reference, you'll need to add the a(href="http://angularfire.com/documentation.html#orderbypriority") orderByPriority | filter. p We're going to need to come back to this later to get the filter working, but this will suffice for now. h3 Create the JavaScript p Create customers.coffee in apps/ang-app/controllers with the following content: p pre define ['./module'], (controllers) -> | controllers.controller 'CustomersCtrl', ['$scope', ($scope) -> | ] p This is just the wrapper we need to create our controller. Now let's add some data. p pre define ['./module'], (controllers) -> | controllers.controller 'CustomersCtrl', ['$scope', ($scope) -> | $scope.customers = [ | name: 'John' | , | name: 'Jane' | ] | ] p We now have an array of customers with two entries, "John", and "Jane". Just one more thing before we check our work. We need to tell Kickstrap to load this controller we've just created. Open _settings.coffee and find code controllers | under code angular | . p Add 'customers' to the end of the list. p pre angular: | controllers: [ | 'messages' | 'products' | 'docs' | 'home' | 'login' | 'customers' | ] p Now we can finally see our page. At /customers.html, we should see our heading, "Customers", an input box, and a bulleted list with John and Jane. p Let's sweeten our creation by using more Bootstrap styling and getting our filter to work. p Back in customers.jade, add code .row | to the first div we created. Under that, add another div with the classes code .col | and code .col-sm-3 | . Nest everything under it. p pre(ng-non-bindable) block content | include _header |   | h1 Customers | div.row(ng-controller="CustomersCtrl") | .col-sm-3 | input(type="text", ng-model="customerFilter") | ul | li(ng-repeat="customer in customers") {{customer.name}} p Let's also prettify the input box with the class code .form-control | . p pre(ng-non-bindable) block content | include _header |   | h1 Customers | div.row(ng-controller="CustomersCtrl") | .col-sm-3 | input.form-control(type="text", ng-model="customerFilter") | ul | li(ng-repeat="customer in customers") {{customer.name}} p While we're at it, let's make this a little more useful and show the customer's email address. Add another line to show code(ng-non-bindable) customer.email p pre(ng-non-bindable) block content | include _header |   | h1 Customers | div.row(ng-controller="CustomersCtrl") | .col-sm-3 | input.form-control(type="text", ng-model="customerFilter") | ul | li(ng-repeat="customer in customers") | span {{customer.name}} | span {{customer.email}} p We had to put these in spans under the li so each customer repeats as a "customer." If we had instead created a new li with its own code ng-repeat | , we'd see all the customer's names all at once, then their email addresses listed separately below. p One more thing, let's make sure our input box actually filters the customers. We'll add a placeholder attribute to tell users how to use the input box p pre input.form-control(type="text", ng-model="customerFilter", placeholder="Filter customers") p Next, change the li to filter based on our code customerFilter | model. p pre li(ng-repeat="customer in customers | filter: customerFilter") p Now let's open customers.coffee and make a few changes so this all works. p pre define ['./module'], (controllers) -> | controllers.controller 'CustomersCtrl', ['$scope', ($scope) -> | $scope.customers = [ | name: 'John' | email: 'john@example.com' | , | name: 'Jane' | email: 'jane@example.com' | ] | ] p Your page should now have two customers which can be filtered with the input box.