Little Known Angular XSRF Protection Support In Http & HttpClient APIs (v2.0+ vs 4.3+)

This post is about a new feature / code restructure in Angular v4.3+ that is pretty well documented, yet, hardly talked about in posts, and worth drawing special attention to.

The feature we are talking about here is Angular helpers for guarding against XSRF attacks in its old and new HTTP modules.

What Is XSRF? (Cross Site Request Forgery)

XSRF (Also knwon as CSRF) is a form of web security attack that can allow others to impersonate your identify and perform some actions on websites that you are already logged in to. Let’s start with an over simplified version of how the attack and protection work (as I understand them).

XSRF Attack

  • You login to website A and get a session cookie, maybe use it a bit
  • You open website B in a new tab or even the same tab, you are still logged into website A
  • The owner of website B (or someone who hacked it) happens to be a user of website A too, and knows what calls it sends to the server to perform different tasks
  • Website B loads a hidden form with the submit URL going to website A
    . It could be sending an email on your behalf, deleting many important items, whatever that is you can perform in website A
  • Website A takes the request and performs it, because you are still logged in

XSRF Protection

There are many ways to protect against this attack. Mainly you’d use server-generated token stored in somewhere that’s not a cookie.

A classic server side application with a single form each page that submits back to the server can generate a token as a hidden field in the form, and then validate it on submit, and generate a new token for the next page etc. Website B will not have a way to generate a valid token when trying to simulate the server form.

A client side application (SPA) could do the same with headers, sending the token in a header when making any API request (A.K.A AJAX call), and getting the new token in the response of that API / AJAX call.

The initial token may be obtained via a call to a known API, or in a cookie that’s downloaded when the HTML page is loaded. Since the other site can only do only put a form on its own page, it cannot modify headers to inject the token, or call the API directly due to CORS (Cross Original Resource Sharing) policy.

Angular HTTP APIs & XSRF Protection

By default the Angular v2+ Http service (from angular/http HttpModule) had builtin support for the Cookies To Headers XSRF protection technique we just mentioned.
If it detects a cookie with the name XSRF-TOKEN, it adds an HTTP header named X-XSRF-TOKEN with the same value to the next HTTP request you make.

Since the support is so transparent, I have seen developers who did not even realise it’s there. If you are a front end developer who had someone else on the backend implement the server issuing and validation of the tokens, you may not even realise it’s there.

But things changed slightly in Angular v4.3, that you probably need to be aware of.

HttpClient

In Angular v4.3, a new library for creating HTTP (AJAX) requests was added to Angular.

Instead of injecting an Http object from @angular/http as you did since v2.0, you inject an HttpClient from @angular/common/http. The new HttpClient has several new features but most notably:

  • Automatically maps responses to JSON by default (configurable)
  • Added a pipeline for injecting middleware to requests/responses (called interceptors, like those of AngularJS v1.x)
  • Has some really cool testing utilities that are much simpler than the old v2.0 Http module

Whether you like it or not, you’ll probably end up using the new HttpClient in your Angular applications. This is because starting Angular v5.0, the old Http will be deprecated (so it may be removed entirely in v6).

For the record, the relatively quiet introduction of the new module in v4.3 and the deprecation of the old in v5 still makes me feel anxious regardless of how good the new one is. The old one generally just worked, and the way it’s replaced reminds me of the 3 router versions that were written during Angular v2.0 pre-releases.

XSRF Interceptors

Since the new HttpClient came with proper support for request and response interceptors, it made total sense for the XSRF support in it to be implemented as interceptors as wel, not as part of HttpClient itself.

This is all cool and good design, but there is a catch, which although is well documented, it’s not having enough people talking about on Medium and Twitter etc.

The XSRF in HttpClient is an opt-in feature. It’s NOT enabled by default, unlike the Http service. This means that you could easily migrate your code from Http to HttpClient and not realise that your builtin XSRF support has been lost, until you test the application and you start getting 403 Unauthorized errors from your API of course.

Luckily, all you need to do to get the support back is just import another module, like:

[pastacode lang=”java” manual=”%2F%2F%20import%20%7B%20HttpModule%20%7D%20from%20’%40angular%2Fhttp’%3B%0Aimport%20%7B%0A%20%20HttpClientModule%2C%20HttpClientXsrfModule%0A%7D%20from%20’%40angular%2Fcommon%2Fhttp’%3B%0A%2F%2F%20…%0A%0A%40NgModule(%7B%0A%20%20declarations%3A%20%5B%0A%20%20%20%20AppComponent%2C%0A%20%20%20%20%2F%2F%20…%0A%20%20%5D%2C%0A%20%20imports%3A%20%5B%0A%20%20%20%20%2F%2F%20Now%20this%20one%20is%20gone%3A%0A%20%20%20%20%2F%2F%20HttpModule%2C%0A%0A%20%20%20%20%2F%2F%20New%20replacement%0A%20%20%20%20HttpClientModule%2C%0A%20%20%20%20%2F%2F%20Restore%20Xsrf%20support%0A%20%20%20%20HttpClientXsrfModule%2C%0A%20%20%20%20%2F%2F%20…%0A%20%20%5D%2C%0A%20%20providers%3A%20%5B%5D%2C%0A%20%20bootstrap%3A%20%5BAppComponent%5D%0A%7D)%0Aexport%20class%20AppModule%20%7B%20%7D” message=”” highlight=”3,17″ provider=”manual”/]

Gotcha

The old HttpModule supported sending the XSRF-TOKEN header for all HTTP requests. While the new HttpClientXsrfModule made sure it doesn’t send the header for GET or HEAD requests.

GET requests don’t make much sense for XSRF attacks anyway because the attack is about changing data while impersonating you (the attacker cannot get the result anyway because of CORS rules). GET requests by definition should not change data.

However, if your API relies on this, your app might break when you move to HttpClient. In that case you might want to look at this Github issue I created and apply the workaround github.com/angular/angular/issues/19885

More Goodies

The HttpClientXsrfModule also makes it easy to change the cookie & HTTP header keys separately if you require that.

Of course you have to remember that both XSRF protection and JSONP require server support as well from the API server you are calling for them to function.

Finally, the same support is also included as opt-in for JSONP requests as well, by adding HttpClientJsonpModule (also from @angular/common/http) to your imports. This utilizes the power of interceptors that allows them to avoid sending an HTTP request completely and do something completely different instead.

As I said, the usage of HttpClient in general, as well XSRF support (and what is XSRF in general) is well documented by the Angular team.
Check it out at https://angular.io/guide/http.
I still noticed that not enough people are talking about this feature and the actual change, so, hopefully this post can bring some awareness to it.

A Very Long Tale of My Career, Or How Teaching NHibernate & Other Backend Stuff Got Me Into Readify

I told a few people how I joined Readify, but I never wrote it down. Here’s more than you ever wanted to know:

Before The Beginning

I didn’t have a computer when I was a kid, until I was 14 or something. I only had access to DOS computer in the mid-to-late 90s in a community center, where I was not allowed to run Norton Commander, because “you won’t learn anything like that”. I learned DBASE III, at the time my teacher was using Windows 95 or 98.

Then I got a computer. Internet came later. I noticed I could be a web developer. PHP was the craze at the time. I jumped on it, and learned some C and Visual Basic too. I didn’t get so far with either.

Then my family moved into another house. My new neighbour who attended a Computer Science college said they had free lectures on Visual Studio 2002 beta during summer, and I couldn’t have missed them! I got the software with a help of the public library I used to go to. The IT manager there was so helpful, even though I was barely allowed in the “grownups” section at the time. That reminds me of something else that’s useless in this context, which is how for over a year I used to note “useful URLs” in a small book, until an affordable Internet Cafe was open in the same library, and I was able to surf like a guru!

My First Company

I started work when I was at uni. I attended a international Microsoft developers conference in Egypt on 2004 and was picked as a best attendee by one of the speakers, to win a Microsoft MCAD training track (8 courses). I was in my first year of 5 years engineering uni.

It wasn’t easy doing a 4 hour training 3 days a week plus uni, but it paid off. I was lucky that most students were senior developers at the time, and all somewhat new to .NET.

A friend recommended me as a trainee in her company in the summer. She left the company, and shortly after, the other 2 developers left on the same day. It was funny. I had to handle this little company myself, with an interesting technical founder who at the time only knew classic ASP. I was interviewing both junior and senior hires technically while still called a trainee!
I also wrote a PoS Windows app that sync’ed with my web app’s SQL DB via Access and DataSets!

My First Move

Then one of the 2 developers who left invited me to work as a freelancer in her company, for a month, with 6 times my full time trainee salary. It was a custom CMS written by someone who left and no one else could wrap their head around the code, and the company needed to extend it in ways it was never meant to work.

That was flattering, and I was crazy about CMSes at the time. I took it, and after a few weeks of day and night work, I decided to dedicate my day to the new work.

It was uni time again (September 2005). My work was successful and led to more work. Eventually someone else left, and he was taking care of a system that nobody wanted to touch for a very different reason. It was in VB.NET! I didn’t know VB.NET at the time, but I took it, and it had some interesting business challenges, and .. em .. KSA remote client management challenges.

I decided to continue working as a part-timer during uni. It was the beginning of crazy era.

The Work – Uni Balance

A New Life

I’d go to uni, finish and head to the company, through a very crowded road (about 2 hours long, including 45 minutes in a single crossing), finish work so late I’m too tired to go home, pull in some chairs together to sleep on, to wake up early enough before anybody comes, and go to uni.

I’d go back home every 2-3 days to change my clothes. I also would take 2-4 weeks off before and during exams. I was so proud I was so rich I could order food whenever I wanted, and was being treated just like all the “big developers”.

Officially A Full-Timer

Then the same person who brought me to the company told me about this American company opening in Egypt, that is always working with pre-release technologies. She said she failed their test because she didn’t take it seriously as the company didn’t seem to have a proper office or anything. She told me she thought she was wrong, as it’s just a different culture. She told me the UX designer I liked the most in our company went to work there.

So, right after finishing a uni final test, I went to this other company for a tech test. It was a horrible idea. I think I did too bad, but having been blogging for a while about tech events in Egypt and other tech stuff, when .NET bloggers were relatively rare at the time (talking 2006), especially in Egypt, I was a well known person to the guys who worked there. Also one of them knew me from a tech forum we both used to help people in.

So, I got to the interview with the tech founder. He’s an Indonesian from a Chinese background, who I think holds a degree from Australia, and is partnering with an American in founding a company in Egypt! He was a legend!

These maybe were some of my best times in life. I worked as a full-time junior developer for pretty much the same salary as my previous company. I worked in the same way I did in the other company plus 10 hours a day in weekends to have 40 hours total. That was doable because our main account was in the U.S., and the time difference was in my favor as I was working mostly by night during uni.

A Senior Title

I really enjoyed the company. The founder made it ever better. He was an awesome geek. He stayed late with me, came on weekends, and sometimes we both would go out to eat or just walk. That was life!

I was the only junior developer at the time. A year later they started hiring junior developers and I was promoted to a senior developer. I was proud I got the title while still a student, even though that didn’t include a pay rise. That came a few months later though.

The company also encouraged me to start public speaking. I was a semi-frequent speaker at the only .NET usergroup in Egypt at the time, and the company itself held its own conference every year, having me as a speaker twice. That was cool, and helped more people recognize me.

The “Experts” Team

After graduating (2008), a friend from the MCAD courses told me his friend left his well-paying online freelancing work to go back to their old company, which was re-opening. It was a part of a very large well known brand in Egypt. He called me to join him in an architecture team they called “The Experts Team”.

It also had the guy I liked the most from the usergroup organizer team. I was getting ready for marriage at the time, and for those who don’t know, marriage costs tens of thousands in Egypt — that’s IF you have an apartment, and I was lucky that my parents suffered from paying loans for many years to ensure I had one before I understood why that was important.

Flying To Abu Dhabi

The Decision I Never Considered

So, I moved to the same team as that friend. I got married. I was happy where I was, working with nice people in a big company. Then the same guy who got me in the company told me about a senior position in a big company in Abu Dhabi. He told me he was called for the opportunity but he felt it was small for him, but OK for me. At first, I rejected the idea. I was still new in my company and wouldn’t want to leave so quick. I also never thought about traveling, but -let me admit- mostly because I never thought I’d be able to do it.

Then someone else from the company encouraged me to take it. My father, whom I thought would say don’t go, encouraged me to go abroad in a way that was very touchy. We are talking 2009. Things weren’t that bad in Egypt, but they were still definitely not good. Having recommendations from the company I didn’t want to leave, and also because the phone interview with my team leader was so nice (He was sure a geek I’d enjoy working with), all led me to go ahead with the offer.

That was the best decision I have taken in my life. Not just because the Egyptian company closed again in a year or two (the parent company thought software was lengthy and expensive compared to integration like SharePoint etc), but also due to political issues later, etc.

Life In Abu Dhabi

I arrived to Abu Dhabi. First time to travel by air. I got freaked out in Abu Dhabi airport when they couldn’t get a scan of my “eye print” and kept me held for an hour. But I was let in! And I started work. I was well respected and had my fame with me, which was nice at first. It wasn’t an oil company but the closest to that (half owned by government). I didn’t have the best salary, but had the highest medical insurance etc.

The Real Beginning

Meligy, The Backend-Focused Speaker

At this time I was all about design patterns and framework design. I had already spoken in the usergroup about all of these. I was being followed by Scott Hanselman on Twitter!

I also went too fast with Entity Framework when it was very new and it screwed me up. I turned to NHibernate, and after joining their mailing list looking for help, I myself became someone who helps others, and someone who interferes with some of the maintainers for how they’d make fun of some of the questions etc. I made good friends with some NHibernate core members. And this was how I heard about Readify.

In February 2010, I was invited by the .NET usergroup I used to speak in, to speak in a big conference they organized, called Cairo Code Camp. It was the 2nd one and I had already spoken at the first. I couldn’t miss it. Scott Hanselman was there. I’ll see him for the first time, AND, as a speaker, both of us, WOW!

I was delivering a session called “Framework Design Guidelines”. That is, stuff inspired by MSDN Patterns and Practices, and Design Patterns and Domain Driven Design.

Someone else was in there, Mitch Denny, the Readify CTO at the time (now in Microsoft U.S.). I enjoyed a nice conversation with him during speaker dinner party, although I didn’t know where he was working at the moment.

My Friend, From The NHibernate Core Team

Now, back to Abu Dhabi. Work was getting boring. I was hoping for some challenging work in U.A.E (Abu Dhabi or Dubai), again, not thinking about travel. It wasn’t very successful. I chatted to my NHibernate core team member friend, and he pointed me to someone he knew, who blogged about his interview process at Readify.

I was pretty impressed. I thought they’ll never take me. There were so many celebrities who worked there that I just knew I won’t be good enough to work there. I tried anyway!

And guess what? They called me back! I learned that Mitch actually remembered me, and knew where he works! I still had to go through a tough interview, and I passed! Hooray!!

The Foolish Call That Made Me Decide To Join Readify

But I wasn’t sure whether I want to make such a big move myself. Fun fact: when they asked me: “which state would you be interested in going to?” I said Sydney only because it was the only city I knew its name (and didn’t remember how I knew it). I wanted to get something extra to weigh the decision.

I DM’ed Scott Hanselman. Didn’t I tell you he was following me on Twitter and knew me in person? I asked for someone who can tell me in all fairness whether Readify was a good company. He pointed me to Tatham Oddie, our current Delivery Lead today :D — He had his phone number on his blog at the time. He picked up the phone once to find an anonymous international caller saying Scott Hanselman recommended him for asking whether Readify was a good company. Of course he wouldn’t say anything bad about his company to a stranger! It was a foolish call, but it was all I needed to get going.

Making The Move

My annual-paid rent was expiring — I had to borrow 60% of my salary to pay that rent (Not having a good enough eyesight for driving made cheaper out of the city options impractical for me). I had to live in a temporary apartment that had legal issues and could have had me kicked out any time because it was cheap and had nice furniture for me and wife. The visa took from April to August, which was very unusual, but it came, and I arrived in Australia!

Since I arrived, so many things happened. I hated Sydney at first because Abu Dhabi was so fancy (I used to move around in latest-model taxi cars, for 6 Dirhams or so — the city was so small). I learned to see the beauty of Sydney only a few months later. My son spoke his first words here, and I and him call it home today.

It’s been long time since arrival in September 2010. During the time I only left Sydney to one-day company annual events in other states, and a one week holiday in Melbourne earlier this year.

Life At Readify

I joined Readify and worked in the same company as so many celebrities I used to fancy, and so many great other people I discovered while working here.

I saw the company go through several growing stages, every time feeling a worry about losing the culture I love in the company, then feeling happy that it is as awesome as ever.

It is definitely an awesome place to work. There’s countless number of great people around here, and I also more than often get to either work at great customer sites with great people I loved to go back to and help with the great work they are doing (my current client is one of them), and other sites that are not as great as I’d hope to see them yet, but instead of feeling feeling bad, I feel inspired to help them make things better bit by bit. Because that’s why you’d hire a Readifarian :)

Yesterday And Today

I got to work with so many clients in different industries, from finance to media to charity to met and livestock handling(!), and many others. I got to play different roles, as a team member, as a mentor, as an appointed tech lead, etc. etc.

I spoke at ALT .NET and SydJS usergroups, and DDD Sydney and NDC Sydney conferences.

And I learned a lot more, not just at work.

I attended several workshops, like Distributed Software Architecture and Messaging by Greg Young, and International Domain Driven Design Tour workshop by Vaughn Vernon. I attended workshops on being a Scrum Product Owner, and a Scrum Master (and learned that I cannot be both at the time time, before they are different interests).

And then I somehow became known as a JavaScript guy. That’s me, who in 2007 was very happy that UpdatePanel in Webforms could abstract AJAX, and thought that people who could write code with Scriptaculous (before jQuery) were magicians. I even run a usergroup for one of popular JavaScript frameworks in Sydney!!!

I’m very proud of what I have done so far, and am still hungry for more learning and achievements. This is a journey that will hopefully never end before I die. One that I wanted to document the past pieces of before I start losing some of the important details.

Thanks for sticking with me till the end. in this long post :)

Cheers,

My Experience Running Jest In A Real Angular CLI Project On Windows

Jest is an alternative test runner by Facebook. It’s popular in React world. I was wondering how it’ll be like in an Angular CLI app. I knew a new semi-empty app won’t be a good enough test, so, I checked it in a real private project I’m working on, so see if it has any benefits for the project and the team.

While I cannot share the project codes, I can still share how the experiment went, as I talked about it yesterday at the ng-sydney Angular usergroup April gathering, also, as I logged it in a related Angular CLI github issue by a friend ng-sydney attendee.

Introduction

For the record, I tried Jest with instructions from @thymikee‘s post (which uses jest-preset-angular), and it worked just fine.

Let me share my findings:

Result Summary

  • It works!
  • It took some small changes.
  • It seemed slower in my case.
  • It caught more errors than Webpack/Karma/Jasmine, which I was very grateful for.
  • The experience is quite different though that I won’t make it the default my team yet.

Required Changes

  • I started with all the steps in the post above.

  • For some libraries I had to follow this github guidance, which made the jest property in my package.json look like:

    "jest": {
    "preset": "jest-preset-angular",
    "setupTestFrameworkScriptFile": "<rootDir>/src/setupJest.ts",
    "transformIgnorePatterns": [
      "^<rootDir>\\node_modules\\(?!ng2-bootstrap|angular2-json2csv|angular2-datatable)."
    ]
    }
    

    The transformIgnorePatterns is the most interesting here. I used \\ because I’m on Windows, and I used ^<rootDir>\\ to try to speed things, although it didn’t make a big difference. There’s also "allowJs": true in "compilerOptions" in src/tsconfig.spec.json.

  • I also had to change the tests. The post mentions all the changes needed (mostly only changing jasmine. to expect. in a few places).

    But there’s another change I had to do, which is removing any expectationFailOutput, which is when you give a custom error message for when a matcher fails to match. Seems Jest does not support that.

Gains

  • Jest seems to run tests in more isolation than the current Webpack/Karma/Jasmine combo, which showed me some errors in my tests that somehow didn’t show before.

  • Jest is reporting which tests are taking too long, the slowness warnings were useful smells to identify not-greatly-written tests.

  • The watch mode is very nice, even though it seems to work off git changes not file watching, which can be confusing at first when you see slightly more files than expected, but it’s still very useful.

Issues

  • As mentioned in Required Changes above, now I cannot use custom error messages in my test matchers (that said, it’s true that default matcher errors are very beautiful and obvious, but still).

  • At the moment, it seems the jest-preset-angular initialization code needs optimization. It doesn’t call polyfills.ts and instead calls its own set, even though it’s optimized for Angular CLI (for example, it uses src/tsconfig.spec.json).

    More importantly, it imports the entire rxjs library, which might hide errors when you forget to import some operators.

  • It’s surprisingly slower than the Webpack/Karma/Jasmine combo!

    For my 196 tests, the Angular CLI v1.0.0 default test runner (with Angular 4) takes ~ 55 seconds, while Jest takes ~100 seconds.

    Update: That conclusion might not be accurate. The time I quoted for each test runner is what the test runner reported. This might for example not include Webpack compilation and browser opening in Karma and might be total time in Jest. If so, then the total time would be the same.
    Thanks @hugoccampos for bringing this to my attention.

  • No browser tests debugging apparently (It might be my ignorance here). A bit harder maybe for those starting testing.

    The Angular CLI does a great job at making testing easy for those not used to it.

  • When Jest itself fails to run, for example if I put a badly formatted regex for transformIgnorePatterns shown above, or mess up something in my src/tsconfig.spec.json file, the errors it shows are very cryptic and tell you nothing that can lead to the real issue (unlike matching errors in tests, which are very nice).

Shared Modules In Angular Apps: Providers Best Practices And What Does `forRoot()` Do?

When you write a shared module for your application, that contains stuff you use in other modules in the same app, you typically want all the services in that module shared only once.

If you just put the services in the providers property of the shared module’s NgModule() decorators, you might get weird cases, especially with lazy loading, when it feels like there’s more than one instance of the service. This is bad if you want to have shared state.

So, there is a better way to write your shared modules:

[pastacode lang=”java” manual=”import%20%7BNgModule%2C%20ModuleWithProviders%7D%20from%20’%40angular%2Fcore’%3B%0Aimport%20%7BCommonModule%7D%20from%20’%40angular%2Fcommon’%3B%0A%2F%2F%20…%20other%20imports%0A%0Aexport%20const%20providers%20%3D%20%5B%0A%20%20%20%20%2F%2F%20…%20your%20shared%20services%20here%0A%5D%3B%0A%0A%40NgModule(%7B%0A%20%20%20%20declarations%3A%20%5B…%5D%2C%0A%20%20%20%20imports%3A%20%5B%0A%20%20%20%20%20%20%20%20CommonModule%2C%20%0A%20%20%20%20%20%20%20%20SomeLibraryModule%2C%0A%20%20%20%20%20%20%20%20…%5D%2C%0A%20%20%20%20exports%3A%20%5B%0A%20%20%20%20%20%20%20%20SomeLibraryModule.forRoot()%0A%20%20%20%20%20%20%20%20…%0A%20%20%20%20%5D%0A%7D)%0Aexport%20class%20SharedModule%20%7B%0A%20%20%20%20static%20forRoot()%20%3A%20ModuleWithProviders%20%7B%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20ngModule%3A%20SharedModule%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20providers%3A%20%5B…providers%5D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%7D%0A%7D” message=”” highlight=”” provider=”manual”/]

The forRoot() pattern / convention is very common in libraries, and you’ll see it in things like ng-bootstrap and others. The name isn’t special for the compiler / framework, but it’s a common pattern.

When using these, in the imports section you can just import the module itself (which gives you any declarations needed like directives etc), and in the exports use the forRoot() version of the module so that it’s available for consumers of your shared module.

Then in your other application modules you can add SharedModule to their NgModule‘s imports normally, except for the AppModule.

The AppModule will be the only place where you add SharedModule.forRoot(), like:

Then in your AppModule, import it as:

[pastacode lang=”java” manual=”%40NgModule(%7B%0A%20%20%20%20declarations%3A%20%5B…%5D%2C%0A%20%20%20%20imports%3A%20%5BBrowserModule%2C%20SharedModule.forRoot()%2C%20…%5D%2C%0A%20%20%20%20…%0A%7D)%0Aexport%20class%20AppModule%20%7B%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

There is one exception to this though. Your tests.

If you are writing any unit tests where you are importing the SharedModule, you will probably need to import the module with its providers, because there is no AppModule in the test.

Something like:

[pastacode lang=”php” manual=”TestBed.configureTestingModule(%7B%0A%20%20%20%20imports%3A%20%5B%20SharedModule.forRoot()%2C%20…%20%5D%0A%7D)%0A…” message=”” highlight=”” provider=”manual”/]

If you haven’t already, have a look at the NgModule official documentation. There’s a main guide, and an FAQ page.

And of course let me know if you have any questions / problems.

Successfully Upgrade Your angular-cli App (Beta 28 & Below) To The Latest @angular/cli Beta


Have you had issues moving from angular-cli beta 28.3 or earlier to the newer versions of the CLI?

Try these steps then!

Global Dependency

This one is as easy as:

[pastacode manual=”npm%20rm%20-g%20angular-cli%20%40angular%2Fcli%0Anpm%20cache%20clear%0Anpm%20i%20-g%20%40angular%2Fcli” provider=”manual” lang=”php”/]

Specific Project

Note: You do NOT need to have the CLI installed globally for this (although it’s a good idea).

First, ensure you have an npm script in your package.json file that looks like:

[pastacode manual=”%22scripts%22%3A%20%7B%0A%20%20%20%20%22ng%22%3A%20%22ng%22%0A%20%20%20%20%2F%2F%20….%0A%7D” provider=”manual” lang=”php”/]

In this tutorial I’ll replace ng calls with npm run ng -- (note final space ) for those people who may not be able to upgrade their global package.

Now, let’s get to real work.

Commit everything you have in git, then:

[pastacode manual=”npm%20rm%20angular-cli%20%40angular%2Fcli%0Anpm%20cache%20clear%0Arm%20-rf%20node_modules%0Anpm%20i%20-D%20%40angular%2Fcli%0Anpm%20run%20ng%20–%20update” provider=”manual” lang=”php”/]

Accept all files from update (which used to be called init) other than app module and component, especially (but not limited to) angular-cli.json, polyfills.ts, package.json and main.ts.

Then go to git undo any unwanted change (deleted packages from package.json, missing scripts or files from angular-cli.json, etc). Undo entire app module and component files if you accepted them by accident.

Then

[pastacode manual=”npm%20install%0Anpm%20run%20ng%20–%20build” provider=”manual” lang=”php”/]

And you can go roll with npm start / npm run ng -- serve.

All good!

Use Yarn Package Manager In Your Angular CLI Projects

Yarn is an awesome tool to reduce the time it takes to install large NPM packages like the Angular CLI. And the Angular CLI is the best tool to kickstart and manage your Angular 2+ projects.

You can use them together, and it’s very easy.

Initial Setup

First, you install Yarn. If you have it installed already, ensure that you have version 0.19.x at least to avoid issues with global packages. You check your Yarn version by running:

[pastacode manual=”yarn%20–version” provider=”manual” lang=”php”/]

Then you need to ensure that the folder where Yarn writes the global packages executable files.

On Windows, the MSI installer should do it for you. For Mac, check the “Path Setup” part in the installation page.

Once done, ensure to open a new terminal after the installation, and test it.

To find what folder to look for:

[pastacode manual=”yarn%20global%20bin” provider=”manual” lang=”php”/]

Then run echo $PATH (Mac) or echo %PATH% (Windows command prompt) to get the PATH variable and check it.

Installing Angular CLI

OK, so yarn is installed, and it’s installed correctly. Let’s get Angular CLI:

[pastacode manual=”yarn%20global%20add%20%40angular%2Fcli” provider=”manual” lang=”php”/]

That’s it!

Adding To A New Angular CLI Project

Starting from beta 31, Angular CLI added native Yarn support.

When you create a new project, the CLI goes and runs npm install for you by default. You can tell it not to by passing a --skip-install flag (-si for short) like:

[pastacode manual=”ng%20new%20test-project%20–skip-install” provider=”manual” lang=”php”/]

Note: The option was called --skip-npm / -sn before beta 31.

But then you’ll have to go run Yarn yourself

[pastacode manual=”cd%20test-project%0Ayarn” provider=”manual” lang=”php”/]

Running yarn by itself is similar to npm install. It’ll read your package.json file and add the packages to node_modules as needed.

Or… you can just tell the CLI to use Yarn instead of NPM!

[pastacode manual=”ng%20set%20–global%20packageManager%3Dyarn” provider=”manual” lang=”php”/]

This way, you don’t need to do anything special when creating new projects. Just go with ng new test-project with no special flags, and the CLI will use Yarn to install the project packages, unless you specify --skip-install.

This is a user-level setting. It does not affect the generated project in any destructive way. It still has a package.json file (because Yarn works just fine with that), and anyone who doesn’t have Yarn can just run npm install.

More on that below. Before that, let’s ensure that everything worked correctly by running npm start or ng serve etc.

All good? Awesome!

Bonus: A Note About Git

When the Angular CLI creates the project, it initializes it as a git repository and git adds all the files it generated. After the Yarn install, you’ll find another file yarn.lock that’s not yet added.

Yarn team recommends adding the file to git, so, you can do just that, and then commit the result as the new project.

[pastacode manual=”git%20add%20yarn.lock%0Agit%20commit%20-m%20%22initialize%20new%20project%20with%20Yarn%20and%20Angular%20CLI%22″ provider=”manual” lang=”php”/]

When you push your repository to a remote server, and someone else pulls it, they can run yarn, or simply npm install (because the package.json file is still there and updated), and get going with the project.

Conclusion

Hopefully that was as simple as you expected it to be. If you have any questions, you can just drop me a comment here, or use any alternative way mentioned in the video.

Don’t forget to sign up for my newsletter so that I can share with you all the resources I use to learn this stuff and more.

Cheers,

Use DIV, TR, or any other tag instead of FORM tag in Angular 2

I got this question in one of my tech Facebook groups today:

In Angular2, Is there anyway for dealing with forms rather than form tag??? As In AngularJS 1.x, there was <form> and <ng-form>.

Is there something like that in Angular2 or we must deal with form tag?!

And the answer is: Yes. It’s possible to create forms without the form tag in Angular 2, with a gotcha…

Here’s how:

Template Driven Forms

If you look for the selector for ngForm directive in Angular2, you’ll find it like that:

[pastacode manual=”form%3Anot(%5BngNoForm%5D)%3Anot(%5BformGroup%5D)%0AngForm%0A%5BngForm%5D” provider=”manual” lang=”default”/]

Note that last one. Any element with ngForm tag <ngForm ...> or attribute <any ngForm ... > should work.

Reference

Reactive Forms (Model Driven)

The selector for formGroup directive is:

[pastacode manual=”%5BformGroup%5D” provider=”manual” lang=”default”/]

Which also means that any element with formGroup attribute should work.

Reference

Gotcha

There is a relatively-big bug with non-form elements used as forms in Angular 2. The submit events do not work.

The implementation is just not as mature as Angular 1.

I have raised a bug here in March, but it’s probably a low priority:

@angular/angular#7807

You might be able to comment on it stating your scenario to bring it some attention.

Angular 2: Here’s how to use jQuery in an Angular CLI project

Please do not take the post as an endorsement of using jQuery with Angular 2. I do not think it’s a good idea. Most stuff you use jQuery for cam be done directly from Angular 2.

However, there might be legitimate reasons for using jQuery, like using jQuery widgets and plugins that do not have a non-jQuery based equivalent. If you are facing that, try this guide:

If you are using the Angular CLI (my personal recommendation), you can use jQuery with Angular 2 in very few and easy steps as follows:

First: Install jQuery, the actual library

[pastacode manual=”%0Anpm%20install%20jquery%20–save%0A” provider=”manual” lang=”php”/]

Then: Install jQuery TypeScript autocomplete

[pastacode manual=”%0Anpm%20install%20%40types%2Fjquery%20–save-dev%0A” provider=”manual” lang=”php”/]

Finally: Go to the ./angular-cli.json file at the root of your Angular CLI project folder, and find the scripts: [] property, add this inside it:

[pastacode manual=”%0A%22..%2Fnode_modules%2Fjquery%2Fdist%2Fjquery.min.js%22%0A” provider=”manual” lang=”php”/]

(or use the slim version if that’s your cup of tea, keep the rest of the path as-is)

After that, jQuery will be available for you as a global variable. You can log jQuery’s version (which is available as jQuery.fn.jquery) to ensure it’s working brilliantly.

How To Get jQuery To Work With Angular 2 CLI – Webpack Edition

I wrote a post yesterday that talked about:
Using Webpack with Angular CLI directly from official Github source
The post seemed to get a bit of traction on twitter, and among other feedback, I got an interesting question in a direct message:

Hi Meligy, Have you tried importing jQuery in Angular-CLI webpack branch project anytime??

Well, turns out I didn’t. I expected it to be just a require(...) / import ... line away. With Webpack, you often don’t need much more than that.

But then when I tried, I found a problem after another, which turned to be very specific to jQuery. It’s an edge case, but for the library the community size of jQuery, it’s worth showing:

A Working Configuration

First, install jQuery:

[pastacode manual=”npm%20install%20jquery” provider=”manual” lang=”sh”/]

Then install jQuery typings:

[pastacode manual=”typings%20install%20dt~jquery%20–global%20–save” provider=”manual” lang=”sh”/]

Adding a test

Then you can modify src/main.ts to include and test jQuery:

  • Add the import:

[pastacode manual=”import%20*%20as%20jQuery%20from%20’jquery’%3B” provider=”manual” lang=”java”/]

  • Change the bootstrap(AppComponent); line to:

[pastacode manual=”jQuery(()%20%3D%3E%20bootstrap(AppComponent))%3B” provider=”manual” lang=”c#”/]

Running it

You can go ahead and run ng serve or ng build -prod. I saw what looked like a TypeScript error in the output, so, go run just that:

[pastacode manual=”tsc%20-p%20src%2F” provider=”manual” lang=”batch”/]

You’ll get an error:

[pastacode manual=”src%2Fmain.ts(11%2C12)%3A%20error%20TS2345%3A%20Argument%20of%20type%20′()%20%3D%3E%20Promise%3CComponentRef%3Cany%3E%3E’%20is%20not%20assignable%20to%20parameter%20of%20type%20’string’.%0Atypings%2Fglobals%2Fjquery%2Findex.d.ts(3218%2C13)%3A%20error%20TS2403%3A%20Subsequent%20variable%20declarations%20must%20have%20the%20same%20type.%20%20Variable%20’%24’%20must%20be%20of%20type%20’cssSelectorHelper’%2C%20but%20here%20has%20type%20’JQueryStatic’.” provider=”manual” lang=”reg”/]

Explaining the problem

This error is because of a conflict between Angular Protractor and jQuery. Angular Protractor defines a global “$” that you use to write your Selenium element selectors nicer, etc. Normally you don’t write real jQuery code in a Selenium test, but Protractor is included in the TypeScript definitions that are included in the entire application.

Working around it

A temporary workaround is to manage the typings files for the website (src folder) and End To End tests (e2e folder) separately.

Each of the the folders have a typings.d.ts file that has (possibly among other things), a typings reference to the root level typings folder:

[pastacode manual=”%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Findex.d.ts%22%20%2F%3E” provider=”manual” lang=”c#”/]

The problem is that the typings/index.d.ts file looks like:

[pastacode manual=”%2F%2F%2F%20%3Creference%20path%3D%22globals%2Fangular-protractor%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22globals%2Fjasmine%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22globals%2Fjquery%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22globals%2Fselenium-webdriver%2Findex.d.ts%22%20%2F%3E” provider=”manual” lang=”asp”/]

Now, we can’t have both angular-protractor and jQuery in the same file, but we cannot modify typings/index.d.ts directly because every time we run typings install, the file will be overridden (and many even add the typings folder to .gitignore).

What we can do though, is replace the reference to it from src/typings.d.ts and e2e/typings.d.ts. When we do, we need to account for path change, we’ll need to prefix the paths with ../typings/ to point to their correct location.

In src/typings.d.ts, we replace the ../typings/index.d.ts reference line with:

[pastacode manual=”%2F%2F%2F%20%3Creference%20path%3D%22globals%2Fjasmine%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Fglobals%2Fjquery%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Fglobals%2Fselenium-webdriver%2Findex.d.ts%22%20%2F%3E” provider=”manual” lang=”c#”/]

In e2e/typings.d.ts, we replace the ../typings/index.d.ts reference line with:

[pastacode manual=”%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Fglobals%2Fangular-protractor%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Fglobals%2Fjasmine%2Findex.d.ts%22%20%2F%3E%0A%2F%2F%2F%20%3Creference%20path%3D%22..%2Ftypings%2Fglobals%2Fselenium-webdriver%2Findex.d.ts%22%20%2F%3E” provider=”manual” lang=”c#”/]

And that should be it. No errors n TypeScript compilation, and running ng serve, then opening http://localhost:4200 shows us that the app still works, with the bootstrap() call now executed from jQuery’s ready call – which we added only to make sure it works!

Run ng build -prod and check the output in dist. You’ll find that it also works well.

Remember, this is only a workaround!

A drawback of what we did is that every time we add typings for a new library using the typings command, we’ll have to add a reference to it manually in src/typings.d.ts and/or e2e/typings.d.ts depending on fit. It’s easy to forget the manual step and get confused.

Luckily though, this is an edge case. Most of the libraries will not have such conflicts (see, that’s why everybody says modules are cool and globals are bad!). For most libraries, all you’ll need to do is to require(..) / import ... a module from the library, and everything will happen magically. Thanks to Webpack, you’ll not even need to setup vendor or systemjs config etc. Check my previous post for more information.

Other ideas

A few other starters seem to have the same problem. One other way to tackle it is to exclude the path typings/globals/angular-protractor from the Webpack config, but currently, I can’t see this config exposed from the Angular CLI. I’m sure it’ll be there once it’s final etc., but it’s not there now.

Another idea is to have a noConflict typings version of jQuery. There’s a pull request to DefinitelyTyped registry to include that, but it’s abandoned and closed at the moment. You can try calling the exact file via typings as a github~ file not dt~. But obviously you miss potential updates.

The best thing that can happen is that the Angular CLI would bring the separation of typings for src code and e2e tests built-in, which may or may not land in the CLI. Let’s see!

Should you use jQuery with Angular 2 at all?

I think the answer is: avoid it if you can.

I’m currently working with a team that has it included, and it was mostly due to needing some UI widgets that are only available for jQuery. I’m hoping that this is going to change with more UI widgets coming standalone, and easy to wrap in Angular 2 components / directives. Many widgets are becoming available with the Angular 2 wrappers already, like the lovely ng2-bootstrap collection.

Use Angular 2 CLI with Webpack Directly from Github Source Code

You have heard the rumour, that Angular CLI is going Webpack. And it’s true. The CLi is replacing broccoli + systemjs with Webpack.

Update 1 (See Update 2 for latest)

The Webpack feature has landed in master GitHub branch!
It’s not on NPM yet (subscribe to my newsletter to get updated when it’s), and it’s in active development.
So, you might still find benefit in trying it out directly from GitHub sources.

Update 2

The Angular CLI has landed on NPM, but you need to call it in a special way:

If you installed Angular CLI before, go [pastacode manual=”npm%20unlink%20angular-cli%0Anpm%20rm%20-g%20angular-cli%0Anpm%20cache%20clear” provider=”manual” lang=”bash”/]
Then to install the Webpack version:
[pastacode manual=”npm%20install%20-g%20angular-cli%40webpack” provider=”manual” lang=”bash”/]

Gotcha

When you run `ng new some-app`, and go inside it and run `ng serve`,
if you might get error like:
[pastacode manual=”No%20angular-cli-build.js%20found.%20Please%20see%20the%20transition%20guide%3A%20https%3A%2F%2Fgithub.com%2Fangular-cli%2Fangular-cli%2Fblob%2Fmaster%2FTRANSITION.md%23user-content-brocfile-transition.” provider=”manual” lang=”reg”/]
To solve this error, you can go to `package.json`, and change
`”angular-cli”: “^1.0.0-beta.11-webpack”,`
to `”angular-cli”: “1.0.0-beta.11-webpack”,`
(remove the `^` from the version)
Then run `npm install`. It should work after that!

You can also skip the initial NPM install using the param `–sn` (skip npm):
[pastacode manual=”ng%20new%20my-app%20–sn” provider=”manual” lang=”bash”/]

Then go fix the package.json file, and run npm install manually, so it only runs once.

Git or Npm?

Depending on how safe you want to go, you might find the master branch of the CLI often having features that are very interesting. This is always the case of course, but it’s more severe as the Webpack move in active as it’s now.

To check the difference, see the release change log vs the git commit log.

I’m not 100% sure of the exact reasons that convinced the team to go this way, but as an end user of the CLI, I expect a few benefits:

  • Easier inclusion of 3rd party dependencies in the build output.

    Instead of having to fiddle with vendor.js file and systemJS config, you just call require("dependency"); and be done with it; where dependency can come from local directory or NPM package, and can be any TypeScript / JavaScript file, or even a CSS / HTML / image file!

  • Easier tree-shaking

    Which means removing parts that are not used in your program from the build output. Angular is betting big on this (mostly via rollup.js library, but possibly via Google closure compiler in the future). Webpack has a few features built-in around this as well.

  • Easier (seamless) Webpack integration

    The current official Angular2 Webpack cookbook says you need to call require("some-name.component.html") in your component’s templateUrl, which is silly because it’s Webpack-only syntax.

    Having tried the Webpack version of the CLI, I’m happy to report that you don’t need to do that anymore.

How to use Angular CLI directly from Github?

So, now that we know why Webpack might be interesting to bring to the CLI, let’s talk about how you can try it even before it’s officially released. That’s if you feel adventurous and want to be on the bleeding edge of course!

Normally you install the Angular CLI npm package by calling:

[pastacode manual=”npm%20install%20angular-cli%20-g” provider=”manual” lang=”bash”/]

Which makes the ng command available anywhere.

Instead, of that, you need to do this:

[pastacode manual=”git%20clone%20https%3A%2F%2Fgithub.com%2Fangular%2Fangular-cli.git%0Acd%20angular-cli%0Anpm%20install%0Anpm%20link%0A” provider=”manual” lang=”bash”/]

Here’s what this will do:

  • Clone Angular-Cli and checkout the webpack branch

    Note that the same method can be applied with the webpack branch where this feature originally landed.

    You just need to call git checkout Webpack (assuming a branch named “webpack”) before npm link.
    This should automatically track the remote webpack branch (as in origin/webpack) if you have a fairly recent version of git.

  • Use the package information in package.json file inside the repository to build and globally install angular-cli NPM package from the contents of the repository.

    To make sure this process succeeds, we installed all the dependencies the repo has. I’m not 100% sure this is needed, but to be safe.

Now when you run the command ng, it’ll come from the version you just downloaded via git. In the future, when you want to update this version you just:

[pastacode manual=”cd%20angular-cli%0Agit%20pull%0Anpm%20install%0Anpm%20link%0A” provider=”manual” lang=”bash”/]

Let’s use it!

Run:

[pastacode manual=”ng%20new%20sample-wp%0Acd%20sample-wp” provider=”manual” lang=”bash”/]

If you try to run ng serve or something similar now, you’ll get an error. This is because ng new downloads a version of the angular-cli into the newly created folder. This is the online version available on NPM directory not the one you have offline, so we need to switch to it.

Ensure that you are inside the new folder created, and call:

[pastacode manual=”npm%20link%20angular-cli” provider=”manual” lang=”bash”/]

Note the difference:

  • When we were inside the git repository and want to use as a global depdendency, we called npm link with no arguments.
  • When we were in a normal project folder, and wanted to replace the local folder version of the depdendency, we called npm link angular-cli, where angular-cli is the name of the package we globally linked before.

Easier Way

Linking can now happen automatically by changing your `ng new` command to:

[pastacode manual=”ng%20new%20sample-wp%20–link-cli” provider=”manual” lang=”bash”/]

After that, you should be able to run the application:

[pastacode manual=”ng%20serve” provider=”manual” lang=”bash”/]

You’ll notice a new output that’s different from what you used to. This is webpack output.

The website will still be available at the usual port 4200. Go to Chrome and open http://localhost:4200 to see it. Modify the app component and see live reload working as usual.

Other things will work normally, like generating components, etc. Check the following command though:

[pastacode manual=”ng%20build%20-prod” provider=”manual” lang=”bash”/]

If you look at the generated output in dist folder, you’ll realise that it’s slightly different due to removal of systemjs.

The size is still quite big at the time of writing though, but this is the area we expect to see more love going to before Angular 2’s final release.

That’s it

Let me know if you enjoyed this post. Say hi on twitter, and sign up to my article updates newsletter.

Bonus Content: Using jQuery

After this post got a bit popular, someone asked me about getting jQuery working with this setup, which showed a particular edge case around protractor and jQuery conflict. Although I wouldn’t generally recommend using jQuery and Angular 2, wrote about how to workaround this conflict, and how to get jQuery to work with Angular CLI and Wepack here.