Subscribe: Jeffry Houser's Blog
http://www.jeffryhouser.com/rss.cfm?mode=full
Added By: Feedage Forager Feedage Grade B rated
Language: English
Tags:
angular  controller  part part  part  state controller  state state  state subview  state  states  subview  text  view  views 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: Jeffry Houser's Blog

Jeffry Houser's Blog



Jeffry Houser's Blog



Published: Sat, 10 Dec 2016 13:20:13 -0700

Last Build Date: Tue, 06 Dec 2016 09:00:00 -0700

 



Data Binding - Introduction to Angular 2 with JavaScript - Part 2

Tue, 18 Oct 2016 09:00:00 -0700

This is the second in a series about building a simple AngularJS application. If you haven't already, check out part 1. This post will expand the sample from the previous article to demonstrate binding in an Angular 2 application. This sample will demonstrate how to bind user input to an Angular 2 display. To do that we only need to make a few architecture changes, and then a bunch of changes to the AppComponent. Architecture Changes Two architecture changes are needed. First, we need to import the Angular Forms library: This loads the Angular library, the uiSelect library, and the angular sanitize library. Angular Sanitize is an Angular library used to parse HTML into Tokens. It is required as part of uiSelect. Some Style sheets are needed too: These are a custom style sheet for the uiSelect directive and the style sheet for Bootstrap. The uiSelect has multiple themes that can apply to it. For the moment, I'm only using the bootstrap theme. All the libraries and CSS sheets are loaded from remote CDNs instead of being hosted locally. Create the Angular Code The next step is to create the Angular code. First, create the Angular module: angular.module('uiSelectTestApp', ['ngSanitize', 'ui.select']); The uiSelect and ngSantitize directives are passed as configuration arguments into our main module. Next, create a controller: angular.module('uiSelectTestApp').controller('ctrl', ['$scope',function($scope){ $scope.dataProvider = [ {id:1, label:'Alabama'}, {id:2, label:'Alaska'}, . . . {id:50, label:'Wyoming'}, ] }]); The controller is named ctrl. It contains a single $scope variable, which is an array. The array contains a list of US states, and will be used to populate the uiSelect component. That is enough for the JavaScript code. Create the HTML The last step is to add the uiSelect component to the page. First, create the Angular app and controller to the page: This code adds the ngApp attribute on the body tag and the ngController attribute on a div tag inside of it. Inside the div, the uiSelect component is implemented: {{$select.selected.label}} There is lots going on here, so let's dissect it one piece at a time. First the main uiSelect: The main uiSelect component contains an ngModel, which acts just like the ngModel on every other angular component you've used. The theme specifies the theme, in this case I specified it to bootstrap. I'm not going to explore themes in this post, but I hope to do so in more detail later. The last attribute is title, which acts like a tooltip when mousing over the component. Next look at the match: {{$select.selected.label}} The uiSelectMatch directive is used to display a label. If an item is selected in the drop down; it will display to the user. If no item is selected the placeholder will display as a prompt. The $select is a service specific to the uiSelect component. We are using it to drill into the selected object and display its label. The uiSelectChoices is used to populate the items that appear in the drop down: The repeat attribute is a loop. It looks over all the items in the dataProvider--which was defined in the controller's $scope. It applies a filter onto those items; using a default one from the uiSelect's $select directive. The default filter searches for any string typed into the uiSelectMatch entry and restricts the display list as such. The span inside the uiSelectChoices determines what is displayed inside the drop down. For my purposes, I just put the label; but you could expand this to include images or other items. The highlight filter is applied to the label, which will highlight the search items in the filtered drop down. Test The App Try the app. This is the app in its default state: This is the app with nothing typed in: This is the app with some filtering: Final Thoughts I was surprised that I had time finding this component when searching through Google for [...]



Using an Angular HTTP Interceptor

Tue, 11 Oct 2016 09:00:00 -0700

I was working on a client project. Two separate AngularJS applications were using the same set of services. The services were using cookies to keep track of server side session data. A small subset of users used both applications and both applications were hosted on the same domain. Did you guess why this is a problem? For users who used both applications, the services could not tell which application the user was using, as such service requests from one app were sometimes being run based on login privileges of the second. This was causing all sorts of problems. The services team decided the best way to accommodate this was to force an argument onto every service request for one of the applications. The server would use this argument to keep the sessions straight. I don't know all the specifics of how the services were implemented, so can't comment on that. But, I can tell you how we modified the Angular code to address this issue. We used an AngularJS HTTP Intercepter . What is an Interceptor? The purpose of an AngularJS HTTP Interceptor is to modify all HTTP requests performed by AngularJS. Y This will affect all requests including REST operations, loading ngInclude files, or loading directive templates. You can set up an interceptor to modify requests before they are sent to the server. You can use it to modify responses before the response is sent back to the result method. An interceptor can also handle request and response errors. When you need to change every service request the application makes to add a new URL argument, this is a great way to do that. Creating the Interceptor A request interceptor must be created in an Angular config block, so here is a config block: angular.module('testModule').config([''$httpProvider", function($httpProvider){ }]); The $httpProvider service is passed into the config function using Angular's dependency injection syntax. The interceptor must be created on the $httpProvider service; which will affect all http requests coming from the app: $httpProvider.interceptors.push(function(){ return { "request" : function(config){ return config } } } This is a basic request interceptor, which performs no functionality yet. $httpProvider.interceptors is an array; and a function is pushed onto it. The function returns an object, which contains properties for each type of interceptor--request, response, requestError, responseError. In this case I only defined a request interceptor. The value of the request is another function. This function accepts a single argument, config that contains configuration data of the request. Then it returns that configuration object. We have not written code to modify the argument yet, but will next. Modify the HTTP Request How you modify the HTTP Requests depends on what you want to do. For my purposes, I wanted to append a query string argument to the request. Without knowing the nature of the request, I won't know if existing arguments already exist or not. My first order of business is to determine if I need to add a question mark to the URL--to start a query string--or an ampersand to add to an existing query string: var queryStringPrepend = "?"; if(config.url.search('\\?') != -1){ var queryStringPrepend = "&" } This creates an argument named queryStringPrepend. This is the value to place before our special query string variable that must be added to all service calls. I default the argument to a question mark for creating a brand new query string. Then I perform a regex search on the config's url to see if it already contains a question mark or not. If the question mark exists then change the queryStringPrepend value to an ampersand. The next step is to add the query string to the configuration's URL: Config.url += queryStringPRepend + "SpecialVariable=SpecialValue" This uses simple string concatenation. Next return the config argument: return config I found this worked for exactly what I wanted. After some experimenta[...]



Aligning Left Text, Center Text, and Right Text with CSS

Tue, 04 Oct 2016 09:00:00 -0700

I was building out an application for a client who wanted pagination on some tabled data. I needed to create a pagination bar that included a previous button on the left, a next button on the right, and a message in the center. In the old days I could implement something like this using tables, however I wanted to see if there was a CSS way to get the same layout. I found two separate, but great, implementations of this. This blog post will explain both of them. Aligning Text with Float My first attempt to implement this was to use the CSS float property. The float means that text moves out of its normal place in the container, usually moving to the left or right of the container. I could float some text to the right, some text to the left and keep some in the middle. Here is the CSS Style for left aligned text: .leftAligned { float : left; } This puts left aligned text to the left side of the div to contain our pagination header. Right aligned text is similar: .rightAligned{ float : right; text-align : right; } The float argument is specified as right so the rightAligned block will move to the right of the container. I also specified a text-align property to move the text all the way over to the right within the rightAligned container. Finally, we need centered text: .centeredText { margin: 0 auto; text-align : center; } This margin property is used to make sure that the centeredText can align right up against the right and left segments. Use these in HTML: Previous/div> Next Displaying 10-20 of 50 Reviewing the code, you need to put the left and right aligned divs first, and the centered text last. This bugged a bit of my OCD, but worked almost perfectly. Play with the code here. The Plunker sample uses some Angular code to simulate the forward and next navigation for sample purposes. As the user was paginating through the data the previous and next links might disappear. When that happened the centered text would change spots. This wouldn't do. We could fix that by adding explicit widths to each div, which worked for the sample application. However my real world app was having problems with that, I believe due to other CSS conflicts. So, I went searching for a second way to accomplish this layout. Aligning Text with CSS Tables My second approach to was to use CSS Tables. You can use the display property in CSS to specify table, or table row or table cell. First, create a table: .table { display:table; width : 100%; } The table CSS style specifies the display type as table and width of 100%. This parallels the HTML table tag. Next, create a table row: .tr { display:table-row; width : 100%; } The table row specifies the display type as table-row. This parallels the HTML tr tag. Now, the left-aligned text: .leftAligned { display:table-cell; width : 25%; } The left aligned text specifies table-cell as the display type. The width is given as 25%. Next, the right aligned cell: .rightAligned { display:table-cell; text-align : right; width : 25%; } The right aligned table cell specifies table-cell as the display. It also right aligns the text with the text-align property and specifies the cell width as 25%. Finally, create the centered text: .centeredText { display:table-cell; text-align : center; width : 50%; } The centered text also has a table-cell type. It also specifies the text-align to center the text; and the width is 50%. The three table cells have a combined width of 100%. Finally, we need to create the table in the HTML. We'll use divs as the controllers. First, create the table div: Inside of that, put a table row: Now put the main content inside the table row: Previous Displaying 11-20 of 50 Next Play with the Code Here. As wit[...]



Passing Parameters to a State - AngularJS UI Router - Part 7

Tue, 27 Sep 2016 09:00:00 -0700

This is part of a series of posts about the AngularJS UI Router. Check out part 1, part 2, part 3, Part 4, Part 5, and Part 6. This is the last entry in this series. I'm going to modify the sample from the previous section to show you how to pass parameters to a state. We'll pass parameters to a headerController and use it to hide the link to the active state. Resolve the Parameter First, we'll need to modify the state definitions in the $stateProvider to pass a value to the views controller. In this case, we'll pass a hard coded string representing the name of the state. Here is the state definition for state1: .state('state1', { url: '/state1', views : { "header" : {templateUrl : 'states/08header.html', controller:'headerController', resolve : { selectedNav : function(){ return "state1" } } }, "mainContent" : { templateUrl : 'states/07state1.html', controller : 'state1Controller' }, "footer" : {templateUrl : 'states/07footer.html'} } }) The header view definition is the one that changed the most. First, a controller, headerController, was added. We'll look at headerController shortly. Then a resolve property was added. The resolve property defines services, on demand, that will be passed to the view's controller. The new services are defined by a function, which returns the value of the service. Whenever the state is activated, the service functions are executed, and once all the service functions are activated the controller is initialized. The definition for state2 is almost identical to state1: .state('state2', { url: '/state2', views : { "header" : {templateUrl : 'states/08header.html', controller:'headerController', resolve : { selectedNav : function(){ return "state2" } } }, "mainContent" : { templateUrl : 'states/07state2.html', controller : 'state2Controller' }, "footer" : {templateUrl : 'states/07footer.html'} } }) The header view of state2 uses the same controller. It also passes in the same selectedNav service. The main difference is the value of that service. For the state1, the value of selectedNav is state1. For state2 the value of the selectedNav is state2. Let's look at the headerController: angular.module('routerTestApp').controller('headerController', ['$scope','selectedNav',function($scope,selectedNav){ $scope.selectedNav = selectedNav; }] ); The headerController is a simple controller. It accepts two arguments, the $scope and the selectedNav. All the code does is copy the selectedNav simple value into a $scope variable so it can be accessed inside the view template. Remove the link to the Active State To remove the link to the active state, open up the header.html file. You should see two links, similar to this: State 1 State 2 To remove the states, the ng-hide will be used. We'll just put together a condition that compares the selectedNav controller variable to the actual selected state: State 1 State 2 This will make things work. Test the App Load the app: The app loads in the default state, state1. You'll see that the link to open state1 is hidden while state1 is displayed. Then click the State 2 link: Once the app enters State2 the State2 link is hidden, and there is only a link to move back to state1. Play with the App here! Resolve can be a very powerful tool and is not limited to simple values. Objects, functions, promise objects, or other services can all be passed as values to a view controller using resolve. Final Thoughts The uiRouter is a great tool for Angular developers who want flexibility when piecin[...]



Add Multiple Views to a Single App - AngularJS UI Router - Part 6

Tue, 20 Sep 2016 09:00:00 -0700

This is part of a series of posts about the AngularJS UI Router. Check out part 1, part 2, part 3, Part 4, and Part 5. One aspect of the uiRouter is that you can add multiple views to a single Angular module. In this sample we're going to create an angular app that has a header, footer, and a main content area, all defined as separate views.. Create the Multiple Views Config In previous samples, we had a lot of nested views. While nested views will work perfectly fine even if you have multiple views, I pulled them out of this sample for simplicity sake. To define the router, go back to the config block: $stateProvider .state('state1', { url: '/state1', views : { "header" : {templateUrl : 'states/header.html'}, "mainContent" : { templateUrl : 'states/state1.html', controller : 'state1Controller' }, "footer" : {templateUrl : 'states/footer.html'} } }) .state('state2', { url: '/state2', views : { "header" : {templateUrl : 'states/header.html'}, "mainContent" : { templateUrl : 'states/state2.html', controller : 'state2Controller' }, "footer" : {templateUrl : 'states/footer.html'} } }) Each state is defined with a name and an object defining that state's properties. The state has two properties. The first defines the state's URL. This is the URL that will show in the browser bar when the state is loaded. The second piece is an object defining the views. Each element of the view object refers to an active view. It tells the router that in the current state, which template each view will display. All view properties are valid here including the templateUrl and controller. I specify the controller on the mainContent views, but for the sake of this sample the header and footer do not have a custom controller. Create the Template HTML Let's create the HTML templates. First, the header.html: State 1 | State 2 I created a simple navigation bar, which includes link to switch between the two states. Now, the footer.html: Copyright notice, contact link, and other footer stuff here! I just put in some placeholder text for common things you might find in the footer of a public web site. Both footer.html and header.html are reused between the two states. Finally, take a look at the state1.html, which will be the main content for the state1 view: {{title}} Other State 1 content The state1.html template references the title from the controller; just as it did in previous samples. It also displays some static placeholder text for state 1 content. This is state2.html which will be displayed when the app is displaying state 2: {{title}} Other State 2 Content The template for state2 is almost identical to state1. The main different is that the description text for fake content refers to State2 instead of state1. Create the Views in the Main Template Finally, you'll have to add all three views to the main template of your HTML application. Previously, we just added the uiView directive with no value. However, when you have multiple views, you must name them so the uiRouter knows which one to direct at which app. Test the App Load the app, and you should see this: The app loaded into the default state of State 1. You can see the navigation bar up top and the footer at the bottom, with the main content in the center. Click the State 2 link: The main content changed, but the footer and header stayed the same. Play with the code here. What's Next The next section of this series will discuss how to pass parameters to a state. We wrote 20 pages on the Angular uiRouter, sign up to get it! First Name Email Address * [...]



Deeper Nesting with Views - AngularJS UI Router - Part 5

Tue, 13 Sep 2016 09:00:00 -0700

This is part of a series of posts about the AngularJS UI Router. Check out part 1, part 2, part 3, and Part 4. In the previous section of this series, we showed a sample of nesting a view inside another. This can be done for as many levels as you need, with a view put inside a view which is inside a view. This entry will show a sample of views that are nested 3 levels deep. Define the Deeper Subviews First, we need to define a subview that goes multiple levels deep. For completeness, here are all the defined states of state1: $stateProvider .state('state1', { url: '/state1', templateUrl : 'states/state1.html', controller : 'state1Controller' }) .state('state1.subview1', { url: '/state1subview1', templateUrl : 'states/state1subview1.html', }) .state('state1.subview1.deeper', { url: '/state1subview2deeper', templateUrl : 'states/state1subview1deeper.html', }) .state('state1.subview2', { url: '/state1subview2', templateUrl : 'states/state1subview2.html', }) }]); The default state is state1. Under state1, there are two states, state1.subview and state1.subview2. This code adds a brand new state, state1.subview.deeper. This is defined as proof of principle that the states can nest multiple levels deep. I left out state2 from the code here as it doesn't apply to this sample. Modify the Subview HTML Open up state1subview1.html file: Sub view 1 Hide Deeper Subview Show Deeper Nested View 1 The top is just text specifying the file being displayed. Next come two links. The first one loads the subview1, essentially hiding the second nested subview. The second links loads the second nested subview. Finally, the uiView directive is used on a div so uiRouter knows where to put the view that is three levels deep. This is the template for the deeper nested view: Deeper Even It is simple with no additional functionality. Test the Deeply Nested Views Load the app and click the "Show Nested View 1" link: Click the Show Deeper Nested View link, and the view that is two levels deep should display: Play with the code here. You can use this approach to build complicated structures with dynamic content. What's Next The next entry in this series will show you how to add multiple views to a single application. We wrote 20 pages on the Angular uiRouter, sign up to get it! First Name Email Address * [...]



Nested Views - AngularJS UI Router - Part 4

Tue, 06 Sep 2016 09:00:00 -0700

This is part of a series of posts about the AngularJS UI Router. Check out part 1, part 2, part 3. The samples this series has created so far have not demonstrated anything that couldn't be done using the ngRoute directive. Now is the time to advance. We'll add two nested views in the first state. Define the Nested State Creating a nested state is just like creating a non-nested state. It supports the sample object properties, such as the name, templateUrl, or controller. There are two ways to tell the uiRouter that this is a nested state. The first is to define the parent state, using a property named parent. I like this because it is a very overt. The second, more common, approach lies in the naming of the state. If a state includes a master state, followed by a period, followed by the state name, then that state is pegged as a substate. Modify the config block to define two nested views: $stateProvider .state('state1', { url: '/state1', templateUrl : 'states/state1.html', controller : 'state1Controller' }) .state('state1.subview1', { url: '/state1.subview1', templateUrl : 'states/state1subview1.html', }) .state('state1.subview2', { url: '/state1.subview2', templateUrl : 'states/state1subview2.html', }) .state('state2', { url: '/state2', templateUrl : 'states/state2.html', controller : 'state2Controller' }) I repeated all states in this app for comparison purposes. State1 and state2 are defined with the state name and few properties. The first substate under state1 is named 'state1.subview1'. The second is named 'state1.subview2'. Each view is defined with a url, and a template, but for the purposes of this example I did not give them a custom controller. They will inherit from state1's controller in this case. The period in the state name defines it as a substate, not the url property in the state object. The url could be anything you desire and is independent of the state name. For the purposes of these samples, I kept the state name and the url identical. Create the Nested Views Let's look at the HTML Behind the two subviews. This is subview 1: Sub view 1 This is subview 2: Sub view 2 Both are simplistic for demonstration purposes. Activate the Nested Views Let's look at the state1.html that will be used to activate the nested views: {{title}} Hide Subview Show Nested View 1 Show Nested View 2 Go to State 2 The title display at the top and the link at the bottom to launch state 2 are the same as was used in previous samples. The middle part is new. It includes three hyperlinks, all using the uiSref directive to display and hide states. The first link goes directly to the state1; which is the default state. That will effectively hide all visible substates. The second link will open the first subview, and the third link will open the second subview. After that we see a div with the uiView directive on it. This is where the subview is displayed in the context of the view. It is similar to how we put the main view on the main index page. Test the Nested Views Load this in an app to test the nested views: The initial state displays all the links, but does not display any of the nested view content. Click the Show Nested View 1 link: Then click the Nested View 2 Link: Test out the code here. What's Next? The next entrie in this series will show you how to nest subviews more than 1 level deep. Multiple layers of nested views is part of what makes the uiRouter powerful. We wrote 20 pages on the Angular uiRouter, sign up to get it! First Name Email Address * [...]



Adding a Controller to a State - AngularJS UI Router - Part 3

Tue, 30 Aug 2016 09:00:00 -0700

This is part of a series of posts about the AngularJS UI Router. Check out part 1 and part 2. When building Angular applications, the views are not useful without an associated controller. An Angular controller provides the business logic behind the view. Thankfully, uiRouter provides a way to associate the state with a controller. Create the Controllers The first thing we're going to do is create the controllers. We can create a controller for each of the two views in the application: angular.module('routerTestApp').controller('state1Controller', ['$scope',function($scope){ $scope.title = "State 1 Controller" }] ); angular.module('routerTestApp').controller('state2Controller', ['$scope',function($scope){ $scope.title = "State 2 Controller" }] ); These are two simple controllers. Each once contains a $scope variable, title, which will be used to replace the hard coded title used in previous examples. Next, edit the config block to tell the $stateProvider which controller should go with which view: $stateProvider .state('state1', { url: '/state1', templateUrl : 'states/state1.html', controller : 'state1Controller' }) .state('state2', { url: '/state2', templateUrl : 'states/state2.html', controller : 'state2Controller' }) The object which defines the state has a new property, named controller. This controller's value is a string that refers to the name of the controller. When the view is setup, the controller will be associated with the view. Create new HTML Templates For this sample, we'll need two new state templates. Instead of using hard coded titles in the template page, it will use a title whose text is populated by the title $scope variable. This is the template for state1: {{title}} Go to State 2 This is the template for state 2: {{title}} Go to State 1 These two templates will show the dynamic title variable as the header, and also still include the links to switch between states. Test The App Now you can load the app and see the changes. This is the initial load: This is what the app should look like after changing to state 2: Play with the full code here. In a real world application, you'll see lots more code in the controllers and interaction in the views. What's Next? The next entry in this series will show you how to nest one view inside of another. We wrote 20 pages on the Angular uiRouter, sign up to get it! First Name Email Address * [...]