I'm reading the ebook Rails, Angular, Postgres, and Bootstrap, Second Edition. I'm really learning a lot. The books it's from 2017, but I'm trying to create the project with all the frameworks updated. I want the hard way. hehehe
So I'm using Rails 6 and Angular 8. I got stuck when I tried to to create a component for angular inside the webpack. How?
I will only describe the steps that I think that it's necessary, so that's what I did:
I create the rails project with:
rails new angular-on-rails
Then I added the angular with webpacker:
rails webpacker:install:angular
After that I created a simple view:
rails g controller dashboard index
And then, inside this view, I added this code:
<hello-angular></hello-angular>
<%= javascript_pack_tag "hello_angular" %>
It works! I can see the Hello Angular in the browser.
After that I tried to create a component called hello-component:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'hello-component',
template: `<h1>Hello component</h1>`
})
export class HelloComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
console.log("Hello Component")
Not forgeting to update the app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello-component/hello-component.component'
@NgModule({
declarations: [
AppComponent,
HelloComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
And the index.html.erb:
<hello-angular></hello-angular>
<hello-component></hello-component>
<%= javascript_pack_tag "hello_angular" %>
I can't see in the browser the Hello Component and there is no errors on the browser console, it shows only the console.log from the hello-component ts file. So the file is being loaded, but not rendering... What am I missing?
I put this simple project in a repository if you want to take a look.
Thank you for your time!
To begin with angular and rails the easy way is to create a project from the scratch: I personally use rvm for ruby gem sets and version management, nvm (node version managemen), yarn and npm (javascript package managers)
At this moment, I think that is easy to integrate react than angular, because angular is a complet framework, not only a frontend library as React so react mix better, really with Angular you have two applications.
rails new testing_angular -B --webpackt=angular
after that, go inside the project
cd testing_angular
bundle install
rails webpacker:install
rails webpacker:install:angular
finally we have all the things to begin, go and work with your favorite text editor at this point I think that the nature of react mix better with rails than angular, but this is only my opinion.
Here you have the basic rails app, that you can run easily with
RAILS_ENV=development bundle exec rails server -b 0.0.0.0
and a complete angular app in app/javascript/hello_angular.
We need to call this app with a new controller
rails g controller hello_angular index
and add the necessary routes in /config/routes.rb
cat config/routes.rb
Rails.application.routes.draw do
root 'hello_angular#index'
get 'hello_angular/index'
end
change the view to render angular like this:
β cat app/views/hello_angular/index.html.erb
<div>
<hello_angular></hello_angular>
</div>
<%= javascript_pack_tag 'hello_angular' %>
With this it should work but we need to fix some things before:
first:
add a file custom.js to config/webpack, in order
cat > config/webpack/custom.js
const webpack = require('webpack')
const path = require('path')
module.exports = {
plugins: [
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core/,
root('../../app/javascript/hello_angular'), // location of your src
{ }
)
]
}
function root(__path) {
return path.join(__dirname, __path);
}
second edit development.js
β cat config/webpack/development.js
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
const {merge} = require('webpack-merge') // update from previous
const customConfig = require('./custom')
module.exports = merge(environment.toWebpackConfig(), customConfig)
then we need to add some dependecies:
yarn add webpack-merge
and I think that this are two bugs that we need to fix.
1) yarn add core-js@^2.5.0
if the project cannot load corejs/es7reflect
You need to modfy this :
cat app/javascript/hello_angular/app/app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'hello_angular', <= fix this selector
template: `<h1>Hello {{name}}</h1>`
})
export class AppComponent {
name = 'Angular!';
}
Finally you can load the project:
RAILS_ENV=development bundle exec rails server -b 0.0.0.0
Started GET "/" for 127.0.0.1 at 2019-10-18 23:00:58 +0200
(0.5ms) SELECT sqlite_version(*)
Processing by HelloAngularController#index as HTML
Rendering hello_angular/index.html.erb within layouts/application
[Webpacker] Compilingβ¦
[Webpacker] Compiled all packs in /Users/toni/learn/ruby/ruby-way/angular-way/testing_angular/public/packs
Rendered hello_angular/index.html.erb within layouts/application (Duration: 9940.3ms | Allocations: 4452)
Completed 200 OK in 12213ms (Views: 12208.3ms | ActiveRecord: 0.0ms | Allocations: 2022052)
then it really work as a pi lets preapre this endpoint, in routes add a route, and add a method to hello_angular controller
http://localhost:3000/hello_angular/world?name=Calimero
{
"name": "Calimero"
}
and add the method to the controller created before:
class HelloAngularController < ApplicationController
def index
end
def world
name = params[:name] || 'world'
render json: { name: name }
end
end
then to render this in angular:
testing_angular on ξ master [?] is π¦ v0.1.0 via β¬’ v12.4.0 via π ruby-2.6.3@way took 39m 30s
β cat app/javascript/hello_angular/app/app.component.ts
import { Component } from '@angular/core';
import {HttpClient} from '@angular/common/http';
@Component({
selector: 'hello_angular',
template: `<h1>Hello {{name}}</h1>
<button (click)="changeName()">Change Name!</button>`
})
export class AppComponent {
name = 'Angular!';
constructor(private http: HttpClient){}
changeName() {
this.http.get('/hello_angular/world').subscribe(data => {
this.name = data['name'];
});
}
}
testing_angular on ξ master [?] is π¦ v0.1.0 via β¬’ v12.4.0 via π ruby-2.6.3@way
β cat app/javascript/hello_angular/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {HttpClientModule} from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
finally you can have the angular app running, please check the ifnal reference and also the complete source code here:
https://github.com/anquegi/testing-angular
and please check this references:
I think you need to add the HelloComponent
also to the bootstrap
array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With