Putting it all together: implementing routing in SPAs

Một phần của tài liệu spa design and architecture understanding single page web applications scott 2015 11 26 Lập trình Java (Trang 123 - 129)

In this section, you’ll take the concepts discussed and illustrated with pseudocode and create a real, working project using AngularJS. In this example, you’ll continue the university theme. Let’s pretend you’re a campus IT staff member tasked with creating a website for one of the university’s departments.

You’ll have three views: a landing view with faculty names to choose from, another view to display the office hours for the person the user selects, and a general contact view for the department.

The user can navigate by either clicking the name of a faculty member in the land- ing view’s faculty list or clicking a navigation link in the header. Also, because you’re incorporating an SPA navigation component, the user will be able to use the browser’s address bar and navigation buttons.

I include the most relevant excerpts from the code here. The complete code is available for download when you want to give the example a try or see the com- plete code for this chapter’s example. Figure 4.6 shows the fin- ished product.

You’ll begin with the exam- ple’s first route, the faculty list route. This is your default route.

As you may remember from ear- lier, the default route is the one used when there’s no match between the current URL and any of the paths in your configuration file. Because the site’s base URL

Figure 4.6 For this example, you’ll create a basic website for a university department.

99 Putting it all together: implementing routing in SPAs

won’t have a match, you should always execute the faculty list route by default. A direct link to the faculty route exists in the header, so this route can be accessed from there as well.

4.4.1 The faculty list (default route)

You saw the pseudocode for the faculty list in our discussion of routes, so let’s create it for real now.

When you use AngularJS’s router, your routes will be configured via $route- Provider. You can use the $routeProvider’s when() method for normal routes and otherwise() to configure a default route. This is specific to AngularJS, though, so don’t worry about that detail. If you’re using a different framework or routing library, you’ll add the same configuration using different syntax.

For now, let’s focus on the concept presented by the route itself. In this route, you’ll use the text /routes/faculty to represent the route’s path (see the following listing).

$routeProvider.when("/routes/faculty", {

templateUrl : "App/components/simplerouter/partials/facList.html", controller : "facultyController"

})

As mentioned earlier, you also want to display the list of faculty members by default.

The next listing shows your default route.

.otherwise({

redirectTo: "/routes/faculty"

})

With this default route in place, you’re immediately redirected to your faculty list when you type the application’s URL into the browser.

THE FUNCTIONALITY BEHIND THE ROUTE

With AngularJS, you can give the name of a registered controller as the functionality to be executed. In other libraries or frameworks, it may be some other type of object or the name of a callback function. In this example, whenever the router finds a URL that con- tains /routes/faculty, the code in the facultyController controller is executed.

Your faculty list’s controller will provide the list of faculty members to be displayed in the view (see listing 4.8). This controller is one of the three defined in our example’s controller file, which also contains the definition for the routeControllers object:

var routerControllers = angular.module(

"RouterApp.controllers", []);

Listing 4.6 Faculty list route

Listing 4.7 Default route The path

The view that gets displayed The functionality

that’s executed

Indicates your

default Redirects back to

the faculty route

To be available in the view, your list needs to be added to AngularJS’s $scope object. As you may remember from chapter 2, $scope is a built-in object, which serves as the

“middleman” between the view and your data (kind of like a ViewModel).

routerControllers.controller(

"facultyController", function($scope) { $scope.deptFaculty = [ { hrefVal : "manderson",

displayText : "Dr. Mary Anderson"

}, {

hrefVal: "sjones",

displayText : "Dr. Steve Jones"

}, {

hrefVal: "arodriguez",

displayText : "Dr. Ana Rodriguez"

} ];

});

In the array you’re making available to the view, you have a list of faculty objects. Each object has two properties: hrefVal and displayText. The hrefVal property will be used in the creation of the link’s URL. The displayText property contains the name the faculty member. You’ll use the faculty member’s name as the visible text of the link.

NOTE The most common practice when using AngularJS is to keep any kind of business logic in an AngularJS service, but we’re breaking that rule here for the sake of keeping this example as simple as possible.

THE FACULTY LIST VIEW

Finally, in listing 4.9, you see the source code for your view. As part of the state changes associated with this route, you’ll display this view, which will contain the data from listing 4.8. Notice that the view’s template uses the properties from the $scope object with the ng-repeat binding to iteratively create the list of links.

<section id="fac_list">

<h1>Our Faculty</h1>

<section id="faculty">

<ul>

<li ng-repeat="faculty in deptFaculty">

<a href="#routes/officehrs/{{faculty.hrefVal}}">

{{faculty.displayText}}

</a>

</li>

</ul>

</section>

</section>

Listing 4.8 The functionality for your route

Listing 4.9 The route’s view

Define the facultyController Add the data for the faculty office hour links to the $scope so it’s available in the view

ng-repeat is used to stamp out anchor tags for each object in the deptFaculty array. The ng-repeat binding tells the framework to create the structure of the

<li> element repeatedly for each item in your list. It works similarly to a for...in loop in JavaScript.

101 Putting it all together: implementing routing in SPAs

After the code fires, your view in facList.html is displayed. The view’s template is ren- dered for each entry in the array. The following listing shows what the first object in the array would look like if you were to inspect the DOM after the template has been rendered. Each HREF in each anchor tag now has a URL and display text.

<li ng-repeat="faculty in deptFaculty" class="ng-scope">

<a href="#/routes/officehrs/manderson" class="ng-binding">

Dr. Mary Anderson </a>

</li>

TIP In AngularJS, you use the special directive ng-view to mark the area where views are to be rendered. You put this directive anywhere in your SPA’s shell, and the $route service will automatically find it and place its views there. Because this is AngularJS-specific syntax, this detail will vary depending on the MV* framework you’ve chosen.

4.4.2 The main contact route

Also in the navigation header of your site is a link to the fictitious department’s main contact view. The link’s code points to a fragment identifier URL:

<a href="#routes/contact">Contact Us</a>

When you click this link, the browser’s fragment identifier changes from #/routes/

faculty to #/routes/contact (see figure 4.7).

Because the router is actively listening for changes in the fragment identifier, this new hash is detected. Upon detection, the router searches all routes in its configura-

Listing 4.10 DOM view of rendered template

Rendered URL

Rendered text

Figure 4.7 Clicking the Contact Us link produces a new fragment identifier in the browser’s URL.

tion for a path matching /routes/contact. When it finds a match, the route in the following listing is carried out.

.when("/routes/contact", {

templateUrl : "App/components/simplerouter/partials/contact.html", controller : "contactController"

})

The controller for this route is contrived, but it provides another view to demonstrate navigation (see the next listing). Again, any real business logic would be placed in another component, such as an AngularJS service.

routerControllers.controller(

"contactController", function($scope) { $scope.mainOffice = "555-555-3000";

});

In contactController, you have only one property: the main office’s contact number.

The following listing shows the view for this route. It displays the main office’s tele- phone number via an expression binding.

<section id="contact_us">

<h1>Contact Us</h1>

<h3>Main Office: {{ mainOffice }}</h3>

</section>

4.4.3 Faculty office hours (parameterized route)

Let’s create one route with a parameter to show how they’re used. When this route is handled, you’ll display the office hours of the faculty member selected from your fac- ulty list view. As with our pseudocode, you’ll start by creating a route with a place- holder for the selected faculty member’s ID (see the following listing).

.when("/routes/officehrs/:facultyID, { templateUrl : "App/components/simplerouter/partials/hours.html", controller : "hoursController"

})

Listing 4.11 Main contact route

Listing 4.12 The functionality for your route

Listing 4.13 The route’s view

Listing 4.14 Office hours route with a parameter The path

The view that gets displayed The functionality

that’s executed

Define the contactController The property to be

displayed in the view

An expression binding for the main office number

Route parameter to pass a faculty member’s ID

103 Putting it all together: implementing routing in SPAs

Each router will have different syntax for route parameters. Consult the documenta- tion for whichever router you choose. This example uses facultyID as the variable name.

THE RELATIVE URL WITH THE TEXT TO BE PASSED

If you view the source in your browser for the links that you print out in your view, each link points to the same route except for the last segment of the URL. Here’s the link for the first faculty member:

<a href="#/routes/officehrs/manderson" class="ng-binding">

Dr. Mary Anderson

</a>

The last part of the link’s URL represents this person’s faculty ID. It was written dynam- ically with your binding. Because you have three faculty members in your list, each member’s URL will contain a different ID.

THE CONTROLLER

To be able to use the information passed via the route parameter, each framework or library will provide a way to access it in your code. AngularJS has the aptly named

$routeParams object. The next listing illustrates your controller’s use of this variable.

routerControllers.controller("hoursController", function($scope, $routeParams) { var contactInfo = {};

contactInfo["manderson"] = { name : "Dr. Mary Anderson", hours : "Tuesday 12-2pm",

email : "manderson@someuniv.edu", phone : "555-555-1111"

};

contactInfo["sjones"] = { name : "Dr. Steve Jones", hours : "By Appointment", email : "sjones@someuniv.edu", phone : "555-555-1112"

};

contactInfo["arodriguez"] = { name : "Dr. Ana Rodriguez", hours : "Wednesday 1-3pm",

email : "arodriguez@someuniv.edu", phone : "555-555-1113"

};

$scope.info = contactInfo[$routeParams.facultyID]

})

Listing 4.15 Controller for office hours

Define the hoursController The object that

provides access to route parameters

Define the office hours and contact information

The route parameter is used to find the correct contact information

In this example, the route parameter passed in will match one of the three contact information entries. Passing the route parameter (the faculty ID) as the property name of the contactInfo object returns the correct faculty member’s information.

Then you can put the information returned into the $scope variable so the view can display it. The following listing provides the view for this route.

<section id="office_hours">

<h1>Office Hours</h1>

<p class="hrs_faculty_name">{{ info.name }}</p>

<p>{{ info.hours }}</p>

<p>{{ info.email }}</p>

<p>{{ info.phone }}</p>

</section>

Now let’s look at the final product. When the user clicks the first link from your fac- ulty list view, and the faculty ID of manderson is passed into the controller via the route parameter, the user sees the screen shown in figure 4.8.

Now that you understand routing, you’ll be using a router from this point forward.

Feel free to refer to this chapter anytime you need a refresher on what you’ve learned.

Một phần của tài liệu spa design and architecture understanding single page web applications scott 2015 11 26 Lập trình Java (Trang 123 - 129)

Tải bản đầy đủ (PDF)

(178 trang)