Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

AngularJS static template


May 08, 2021 AngularJS


Table of contents


Angular template

It's time to create a dynamic web page with AngelJS. We'll add a test to verify the code for the controller, and we'll add the controller.

There are many ways to construct code for an application. F or Angular applications, we encourage the use of module-view-controller (MVC) design patterns to decouple code and separate concerns. With this in in perspective, we use small Angular and JavaScript to add modules, views, and controller components to our applications.

  • Now the following data dynamically generates a list of three phones:

Reset the workspace to the second step

git checkout -f step-2

Refresh your browser or check this step online: Step 2 Live Demo

The most important differences between the first and second steps are listed below. You can see the full difference in GitHub.

Views and templates

In Angular, the view is a map of the module through an HTML template. This means that whenever the module changes, Angular refreshes the appropriate binding point and updates the view.

Angular structured the view components using the following code as a template:

app/index.html :

<html ng-app="phonecatApp">
<head>
  ...
  <script src="/attachments/image/wk/angularjs/angular.js"></script>
  <script src="/attachments/image/wk/angularjs/controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl">

  <ul>
    <li ng-repeat="phone in phones">
      <span>{{phone.name}}</span>
      <p>{{phone.snippet}}</p>
    </li>
  </ul>

</body>
</html>

We replace the hard-coded list of phones with the ngRepeat instruction and two Angular expressions:

  • The <li> ng-repeat="phone in phones" on the element label is an Angular transponder instruction. The transponder tells Angel to create an element for each phone in the list that uses the element tag <li> as a template. <li>
  • Expressions surrounded by braces {{phone.name}} {{phone.snippet}} will be replaced with the value of the expression.

We've added a ng-controller that adds a PhoneListCtrl controller to the element tag. At this point:

  • Expressions in parentheses {{phone.name}} and {{phone.snippet}} represent bindings, and they are cited in our application modules, and they are set PhoneListCtrl controller.
Note: We've specified an "Angular Module" (https://docs.angularjs.org/api/ng/type/angular.Module) to load the use of 'ng-app' 'phonecatApp', where 'phonecatApp' is our module name. The module will contain 'PhoneListCtrl'.
AngularJS static template

Modules and controllers

The Data module (a simple series of phones, expressed literally as object notation) is now instantiated in the PhoneListCtrl controller. The controller is just a constructor function and requires a $scope parameter:

app/js/controllers.js :


var phonecatApp = angular.module('phonecatApp', []);

phonecatApp.controller('PhoneListCtrl', function ($scope) {
  $scope.phones = [
    {'name': 'Nexus S',
     'snippet': 'Fast just got faster with Nexus S.'},
    {'name': 'Motorola XOOM? with Wi-Fi',
     'snippet': 'The Next, Next Generation tablet.'},
    {'name': 'MOTOROLA XOOM?',
     'snippet': 'The Next, Next Generation tablet.'}
  ];
});

Here, we declare a controller called PhoneListCtrl and register it in an PhonecatApp Note that our ng-app instruction (on the element tag <html> now phonecatApp module name as the mounted module, which is loaded when booting the application of the Angulal application.

Although the controller doesn't do much, it plays a vital role. B y providing data modules for our context, the controller allows us to establish data binding between modules and views. Let's add dot dashed lines between the presentation, data, and logical components, as follows:

  • The ngController directive, located <body> label, refers to the name of our controller, PhoneListCtrl (placed on the JavaScript file controllers.js
  • PhoneListCtrl $scope data to our controller function by attaching it to the computer. T he scope is a prototyped descendant of the root scope, which was created when the application was defined. The controller scope can be used at all binding locations within the element label <body ng-controller="PhoneListCtrl">

Scope

The concept of a scope is crucial in Angular. S copes can be considered adhesives, allowing templates, modules, and controllers to work together. A ngular uses scopes, as well as information contained in templates, data modules, and controllers, to keep modules and views separate, but synchronized. Any changes to the module affect the view;

To learn more about the Angle scope, see the angular scope documentation.

Test

Separating the controller's "Angular method" from the view makes it easy to test the code as if it were being developed. If your controller is available in the global namespace, we can simply instantiate it with a simulated scope object:

test/e2e/scenarios.js :

describe('PhoneListCtrl', function(){

  it('should create "phones" model with 3 phones', function() {
    var scope = {},
        ctrl = new PhoneListCtrl(scope);

    expect(scope.phones.length).toBe(3);
  });

});

Test the PhoneListCtrl verify the phone series properties on a scope that contains three records. T his example demonstrates how easy it is to create a unit test for code in Angular. Because testing is such a critical part of software development, we make it easy to create tests in Angular so that developers can be encouraged to write them.

Test non-global controllers

In practice, you should not want your controller functions to be in the global namespace. Instead, you can see that we have registered the controller with an anonymous constructor function on a phonecatApp module.

In this case, Angular provides a service that $controller which can receive your controller by name. Here's $controller using the code:

test/unit/controllersSpec.js :

describe('PhoneListCtrl', function(){

  beforeEach(module('phonecatApp'));

  it('should create "phones" model with 3 phones', inject(function($controller) {
    var scope = {},
        ctrl = $controller('PhoneListCtrl', {$scope:scope});

    expect(scope.phones.length).toBe(3);
  }));

});
  • Before each test starts, we tell Angular to load phonecatApp module.
  • We asked Angular to $controller the inject into our test function.
  • We use $controller to create an PhoneListCtrl
  • Using this example, we checked the phone number column properties on a scope that contains three records.

Write and run tests

Angular likes to use Jasmine's behavior-driven development (BCC) synth. A lthough Angel doesn't ask you to use Jasmine, in this tutorial we wrote all the tests with Jasmine v1.3. You can learn about Jasmine in jasmine's official home page and Jasmine documentation.

The angular-seed project is preprocessed to run unit tests using Karma, but you will need to make sure that Karma and its necessary plug-ins are installed. You can do rpm install

To run the test, run rpm test see what happens to the file.

  • Karma will automatically start a new instance of Chrome and Firefox. J ust ignore them and let them run in the background. Karma will use these browsers for test execution.
  • If you already have one of these browsers installed on your machine, be sure to update Karma's profile before you run the tests. The local profile test/karma.conf.js browsers

    For example, if you only have Chrome installed:

      ...
      browsers: ['Chrome'],
      ...
    
  • You will see the following or similar output at the terminal:

      info: Karma server started at http://localhost:9876/
      info (launcher): Starting  browser "Chrome"
      info (Chrome 22.0): Connected on socket id tPUm9DXcLHtZTKbAEO-n
      Chrome 22.0: Executed 1 of 1 SUCCESS (0.093 secs / 0.004 secs)
    

    Yes! T he test passed! Or failed to pass...

  • To re-run the test, you only need to change any source .js files. K arma will notice these changes and will re-run the test for you. Isn't it sweet now?
Make sure you don't minimize Karma's open browser. In some operating systems, the memory allocated to a minimized browser is limited, causing your karma test to run extremely slowly.

Experiment

  • Add another .html the index.html For example:

    <p>Total number of phones: {{phones.length}}</p>
  • Create a new module property in the controller and bind it to the module from the template. For example:

    $scope.name = "World";

    Then add a .html binding to the index.html

    <p>Hello, {{name}}!</p>

    Refresh your browser to see if it says "Hello, World!"

  • Update ./test/unit/controllersSpec.js to reflect previous changes. For example, add:

    expect(scope.name).toBe('World');
  • Create index.html in index, which structures a simple table:

    <table>
      <tr><th>row number</th></tr>
      <tr ng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>{{i}}</td></tr>
    </table>

    Now let this 1-based list of i to the binding 1.

    <table>
      <tr><th>row number</th></tr>
      <tr ng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>{{i+1}}</td></tr>
    </table>

    Also note: Try and make an 8x8 table use an additional ng-repeat

  • The unit expect(scope.phones.length).toBe(3) into toBe(4)

Summarize

Now you have a dynamic app that splits the modules, vision, and controller components, and you tested them. Now, let's go to Step 3 Filter Iterator to learn how to add a full-text search to your app.