Check out our Angular Book Series.

How do I send JSON to a Server in Angular 2+?

I have a lot more trouble answering Angular questions on StackOverflow than I did answering Flex questions. The bulk of Angular problems seem to come from integrating different systems and libraries together. But, every once in a while I see a question that I seem to be the perfect person to answer. This question is about Sending JSON from Angular to PHP. I wrote a book about that.

When sending JSON to PHP--or Java or ColdFusion or any server side tech--you need to be sure to set the headers to application/json.

If you are using Angular 2, this is how you do it:

let optionHeaders : Headers = new Headers();
optionHeaders.append('Content-Type', 'application/json');
let options: RequestOptions = new RequestOptions({headers:optionHeaders});
this.http.post(serverEndPoint, JSONPayload,options);

We create an instance of a RequestOptions object, and add the Headers onto it. The RequestOptions object is sent as part of your server request, in this case using a post() method. This is all part of the now deprecated Http library.

Angular 5 introduced the new HttpClient library, which does things a bit differently:

let options : Object;
let optionHeaders : HttpHeaders = new HttpHeaders().set('Content-Type', 'application/json');
options = {headers:optionHeaders};
this.http.post(serverEndPoint, JSONPayload,options);

You create a generic options object, and add an HttpHeaders() instance inside of it. Send that as the options argument to the http method, also a post().

Debug an Angular Application with a Chrome Plugin

I just discovered Augary, a Chrome Plugin for debugging angular applications. I can't believe I never came across this before.

Install Augary and then an Augary tab will appear as part of the Chrome Debugger tools. Here it is for the Learn With application:

Instead of trying to unravel the application through compiled source files and some guesses, Augaray models out the application for you and allows you drill into services, components, and routes to give you a deeper understanding of what is going on in your Angular application.

I've been playing around with it and it is pretty awesome.

How to specify the CSS extension when generating a Component with Angular CLI 6?

I created a brand new Angular CLI 6 project:


ng new foo --style=scss

I wrote about this in another blog post.

Now generate a component:


ng generate component myComp/display

As expected, the new component is generated using SCSS:

That's good. But, what if you want to use something other than the project settings, like creating a normal CSS file as part of your new component or using the styleext command line argument:


ng generate component myComp/otherdisplay --styleext=css

Now look at the generated files:

It changed the SCSS files from the first command to CSS Files in the second command. In case you are experimenting with different preprocessors for whatever reason, this has you covered.

How do I modify an existing Angular6 Project to use SASS?

If you haven't done so already, you may want to read last week's post about generating an Angular 6 project to use SASS instead of regular CSS files. There is a ton of documentation out there on how to do this for Angular 5 or before and they direct you to use ng set to modify the Angular config file. None of that works for Angular 6, because the

get/set have been deprecated in favor of the config command.

I had two problems. First, I found the documentation on how to use the config command a bit lacking. Second, you already have to know the properties you want to change before you can use the command.

Create a new project that is set to use SCSS and you'll find something like this:


"projects": {
"myAppSetToUseCSS ": {
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
},
....

This is what we want to create in our SASS-free project. Here is the command to add it to a new project:


ng config projects.myAppNotSetToUseCSS.schematics.@schematics/angular:component.styleext scss

You won't get a command line response, but your angular.json will not be updated.

If you want to CSS files that were already modified, you'll have to change them on your file system--and any code that references them such as a @component metadata. Be sure to open up the angular.json file and change the other defaults:


"projects": {
"myAppNotSetToUseCSS": {
"architect": {
"build": {
"styles": [
"src/styles.scss"
],
"test": {
"options": {
"styles": [
"src/styles.scss"
],
....

Those are the only two references to the default styles folder for the main project, but be sure to do a file search through your Angular.json file just to make sure.

How to set up an Angular 6 Project to use SASS?

I've been doing some architecture work on a new project, and setting up the project infrastructure using Angular 6 CLI. Without thinking I created a project normally.


ng new foo

You'll see something like this:

Notice that the CSS Files generated have the CSS extension. That's not what I wanted, SASS files have the scss extension. To tell Angular CLI how to create a project using SCSS files, you need to specify the style command like attribute:


ng new bar --style=scss

Now look:

The files are properly updated. Next week, I'll show you how to update a project that was already generated to make it use SCSS by default.

My Angular 6 Books are Out

Aside from being swamped with client work, I've just updated the Learn With series for Angular 6.

This is a relatively minor update as there were not a lot of changes between Angular 5 and 6, but if you want to find out the information on the latest version that is the best way to get it.

Right now I'm working on a series of longer articles about using Redux and Angular. They should be out soon.

What are Route Guards in Angular?

When you build an Angular application, you're probably going to use a router. The router is a library that allows you to change the URL of the application, and with that URL change to load new components. How do you protect parts of your application from being accessed by users who are not authorized? You use a Route Guard.

What is a Route Guard?

A Route Guard is code that Angular will execute when processing the route. I have been using one to determine whether a user should have access to the route or not. However, they can be used for any purpose. There are a handful of different hooks that can be used:

  • CanActivate to mediate navigation to a route. This is the one I'll demonstrate today.
  • CanActivateChild to mediate navigation to a child route.
  • CanDeactivate to mediate navigation away from the current route.
  • Resolve to perform route data retrieval before route activation.
  • CanLoad to mediate navigation to a feature module loaded asynchronously.

That list is copied from the documentation, because I don't think a lot of elaboration is needed.

Using CanActivate

I'm going to use modified code from my latest book on Angular 6, which you should get if you want a beginner's introduction to Angular.

The first step is to create a Service:


import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate {
constructor() {}
canActivate() {
return userHasLoggedIn
}
}

The guard is marked as Injectable and implements the CanActivate method. I greatly simplified the algorithm for determining whether a user has logged in or not, but it can be as complex as you need it. I'm just returning a Boolean value. If the user has logged in--via the userHasLoggedIn value, then the user can activate this route and the canActviate() method returns true. If the user has not logged in, then canActivate() returns false and Angular will know now to load the route.

Since this is a service, load it in your module. In the LearnWith books, I set up a module strictly for routing purposes, so it looks something like this:


import {AuthGuard} from "./auth-guard.service";
@NgModule({
imports: [ RouterModule.forRoot(ROUTES) ],
exports: [ RouterModule ],
providers: [AuthGuard],
})

A constant named ROUTES defines the application's roots:


const ROUTES : Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'GotIn', component: MainApplicationComponent, canActivate: [AuthGuard] },
];

The object which defines the router has a canActivate property and uses the AuthGuard class as it's value. So, when the user purposely tries to load the GotIn route, the canActivate() method inside the AuthGuard class will execute and determine whether the user can view this route based on their logged in status.

Route Guards a powerful and something to learn if you care about the security if your application.

Be sure to pick up my full book series on Angular 6.

Using Angular, RXJS, and SystemJS

just updated DotComIt's build scripts for building Angular 6 applications. I wrote these before the AngularCLI was king of the heap and keep these around because I haven't had time to update my LearnWith series, which contains an introduction to Angular.

Anyway, I copied my Angular5 scripts, updated the package.json to a bunch of new versions, build the sample app, and then started getting errors from the application:


Error: Unexpected token <
Evaluating http://local10.dciseed.dot-com-it.com/Angular6TypeScript/build/js/rxjs

My local dev server has directory browsing turned on, so instead of loading the actual files behind rxjs it was trying to load the directory listing. That won't work. I also saw this error in my experimentation, which said that '"rxjs/operators" not found'. Supposedly that issue was fixed long before RXJS 6.0.0, but alas I was still seeing it.

The solution was to list all the rxjs directories as a package inside of SystemJS Config:


packages: {
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js' },
'rxjs/operators': {main: 'index.js', defaultExtension: 'js' },
'rxjs/testing': {main: 'index.js', defaultExtension: 'js' },
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js' },
rxjs: { main: 'index.js', defaultExtension: 'js' }
}

It took me a while to find this solution, and even then I couldn't get it to work until I removed the quotes around the last package definition.

Weird stuff,

How do I test the text of an HTML Element with Jasmine, Karma, and Angular?

I think this should have been simple, but my Google Fu was failing me. I'm working on an Angular app, as I often do, and was writing unit tests to verify that property changes inside a Component's class were reflected inside the view template.

The Component and View

I'm just going to use truncated code here, but the component had a property like this:


export class MyClass{
@Input() buttonText : string = "";
}

The template had something like this:


<button class="myButton">{{buttonText}}</button>

Change the value on the component, and the view should change. This sort of binding is basic to Angular. How do we test that?

Write the Tests

First, you set up the TestBed:


beforeEach(async(() =>
{
TestBed.configureTestingModule({
declarations: [ MyComp ]
})
.compileComponents();
fixture = TestBed.createComponent(MyComp);
component = fixture.componentInstance;
}));

This should be pretty standard, and this code is almost copied verbatim from the Angular CLI defaults.

Now your test should do something like this. First set the value on the component


const defaultButtonText = "Something"
component.buttonText = defaultButtonText ;

Now you have to detect the changes to force the view to refresh itself:


fixture.detectChanges();

Get the HTML Element:


const button = fixture.debugElement.query(By.css('.myButton'));

And check the button's TextContent:


expect(button.nativeElement.textContent.trim()).toBe(defaultButtonText )

You're code should be all set to test.

For completeness, here is the full test:


it('Set Button Text to Something', () =>
{
const defaultButtonText = "Something"
component.buttonText = defaultButtonText ;
fixture.detectChanges();
const button = fixture.debugElement.query(By.css('.myButton'));
expect(button.nativeElement.textContent.trim()).toBe(defaultButtonText )
});

I hope this helps someone.

How do I listen for an Angular Event in TypeScript?

I'm building a custom Angular service for a client project that will create modal and other popups. If certain interaction occurs within the modal, then the modal should dispatch an event and the service needs to close the modal. In Angular you can use an EventEmitter to dispatch the event from the component's class. Create the emitter as a property on the component's class and add the @output metadata:


@Output()
myEvent : EventEmitter<any> = new EventEmitter();

Then to dispatch the event use the emit method:


this.myEvent.emit('Emitted Value');

That does exactly what I need in the component side. However, to listen for the event, most of the documentation I can find talks about doing so in the HTML template:


<MyComp
(myEvent)="onMyEvent($event)">

</MyComp>

Unfortunately, the service cannot add that event handler onto HTML because there is no HTML, so that was a no go for my use case. How do you do it?

After the service creates the component and displays it, it has an instance to that component class. We can introspect into the component class to get access to the emitter, and subscribe to it:


myCompRef.instance.myEvent.subscribe((value) =>
{
// do something
});

Under the hood the EventEmitter is a Subject, which is like an Observable.

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.