Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Rails 5에서 Angular 사용하기

당신은 전에 이야기를 들었습니다. 분산되고 완벽하게 작동하는 백엔드 API와 일반 도구 세트로 만든 프론트엔드에서 실행되는 애플리케이션이 이미 있습니다.

이제 Angular로 이동하려고 합니다. 또는 이러한 방식을 선호하기 때문에 Angular를 Rails 프로젝트와 통합하는 방법을 찾고 있을 수도 있습니다. 우리는 당신을 비난하지 않습니다.

이러한 접근 방식을 사용하면 두 세계를 모두 활용하고 Rails 또는 Angular의 기능을 사용하여 형식을 지정할지 여부를 결정할 수 있습니다.

우리가 만들 것

걱정할 필요가 없습니다. 이 튜토리얼은 이러한 목적으로 작성되었습니다. 사용자 도메인에서 완전히 작동하는 CRUD 응용 프로그램을 만드는 방법에 대해 자세히 알아보겠습니다.

이 기사의 끝에서 Angular에 대한 몇 가지 기본 개념과 아래와 같이 프론트엔드용 Angular와 직접 통합되는 Rails 백엔드 프로젝트를 설정하는 방법을 배우게 될 것입니다.

Rails 5에서 Angular 사용하기 Rails 및 Angular로 만든 사용자 CRUD

애플리케이션은 외부 가짜 테스트 웹 서비스에서 검색된 사용자 도메인에 대해 네 가지 CRUD 작업을 모두 처리합니다. 앱은 MVC 아키텍처를 기반으로 구축되며 각 Angular 레이어는 어떻게 연결되는지 더 잘 이해할 수 있도록 자세히 설명됩니다. 스타일은 부트스트랩에 달려 있습니다.

설정

짐작하셨겠지만 다음 소프트웨어가 필요합니다.

  • Ruby(저는 버전 2.7.0preview1을 선택했습니다),
  • Ruby와 Rails(저는 5.0.7.2 버전을 사용 중입니다),
  • Node.js(저는 v13.7.0으로 갈 예정입니다),
  • 얀(최소 버전 1.22.4)

모든 것이 올바르게 설치되었는지 확인하십시오. 그런 다음 프로젝트를 진행할 수 있습니다. 원하는 폴더를 선택하고 다음 명령을 실행하십시오:

rails new crud-rails-angular

설정이 완료될 때까지 기다렸다가 선호하는 IDE 내에서 프로젝트를 엽니다. 이 기사에서는 VS Code가 간단하고 강력하며 Rails와 Angular 구문을 모두 부드럽게 수용하기 때문에 우리는 VS Code로 작업할 것입니다.

Rails 5를 한동안 사용해 왔다면 new 명령은 Gemfile 내에서 버그를 생성합니다. SQLite 구성을 위해. 최소 버전 없이 제공되며 오류와 함께 실행됩니다. 업데이트하여 이 문제를 해결해 보겠습니다.

gem 'sqlite3', '~> 1.3.10'

완벽합니다!

웹패커 설정

Rails에서 JavaScript와 유사한 애플리케이션을 관리하는 가장 좋은 방법은 Webpacker를 사용하는 것입니다. Webpack을 사용하여 Angular와 같은 JavaScript 앱을 사전 처리하고 기존 Rails 애플리케이션에 번들로 묶는 것과 같은 기능을 제공합니다.

설치하려면 Gemfile에 새 줄을 추가하기만 하면 됩니다. :

gem 'webpacker', '~> 4.3.x'

이렇게 하면 최신 버전을 설치할 수 있습니다. 다음으로 다음 명령을 실행합니다.

bundle install
bundle exec rake webpacker:install
bundle exec rake webpacker:install:angular

첫 번째 명령은 추가된 Rails 종속성을 다운로드하고 업데이트합니다.

두 번째는 npm install과 동일합니다. node_modules를 생성하기 때문에 폴더를 만들고 Babel, Sass, Browserlist 및 Webpack과 같은 필수 Angular 종속성을 설치합니다. 이제 동일한 프로젝트에 Node 및 Rails 앱이 있습니다.

최신 명령에는 npm install angular에 해당하는 항목이 있습니다. , 모든 Angular에 필요한 종속성을 다운로드하고 Rails 프로젝트와 함께 작동하도록 합니다.

이 명령의 끝에서 package.json도 볼 수 있습니다. 파일이 생성되었습니다. 필요한 모든 종속 항목이 여기에 배치되며 나중에 필요한 항목을 추가할 수 있습니다.

또한 /app 아래에 일부 폴더와 파일이 생성되었습니다. 폴더(예:새 /javascript) . 이 폴더에는 이미 /hello_angular 파일이 있습니다. 개발 시작을 지원하기 위해 생성된 폴더입니다.

시간을 내기 위해 다음과 같이 폴더와 파일 구조를 미러링하도록 요청하겠습니다.

Rails 5에서 Angular 사용하기

일부 각도 조정

Webpacker는 생성된 Rails 프로젝트 내에서 일련의 조정을 권장합니다. 그러니 시간을 내어 집을 정리합시다.

먼저 application.js를 엽니다. /packs 아래에 있는 파일 폴더(위 그림 참조)에 다음 코드를 추가합니다.

import "core-js/stable";
import "regenerator-runtime/runtime";

이러한 가져오기는 Rails 프로젝트 내에서 JavaScript 환경을 안정화하는 보조 역할을 합니다.

이제 페이지의 출력을 선택해야 하는 위치를 Rails에 알려야 합니다. Webpacker가 포장을 마치면 Rails가 알고 있어야 하는 배포 가능한 정적 파일 묶음이 생성됩니다.

application.html.erb로 이동합니다. app/views/layout 아래의 파일 폴더를 만들고 <head>를 변경합니다. 콘텐츠를 다음에 태그:

<head>
  <title>CrudRailsAngular</title>
  <base href="/" />
  <!-- 1 -->
  <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous" />
  <!-- 2 -->
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application' %>
  <!-- 3 -->
</head>

이를 조금 분해해 보겠습니다.

  1. 여기에 base를 추가합니다. 애플리케이션이 시작될 때 찾을 위치를 Rails에 알려주는 태그입니다.
  2. 부트스트랩을 사용하여 페이지의 스타일을 유추하므로 구현에만 집중할 수 있습니다.
  3. 여기에 /packs에 매핑되는 Webpacker 태그를 배치해야 합니다. 폴더 콘텐츠(모든 컴파일 후 Webpacker에 의해 자동 생성되는 것과 동일).

모델 및 데이터베이스

데이터베이스 설정으로 이동합니다. 작업을 더 빠르게 하기 위해 User라는 새 모델을 스캐폴드합니다. . 다음은 이를 달성하기 위해 실행해야 하는 명령입니다.

rails g scaffold User name:string age:integer address:text && rake db:migrate

Rails가 데이터베이스 정보(SQLite에서)를 조작하고 CRUD 작업에 저장하도록 하는 데 필요한 모델의 모든 폴더와 파일을 생성합니다.

그러면 새 파일 XXX1_create_users.rb가 표시됩니다. db/migrate/ 아래에 생성되었습니다. 폴더. 열면 새로 생성된 CreateUsers가 표시됩니다. 기록.

앱/모델/ 내 폴더에 생성된 User가 표시됩니다. user.rb의 모델 파일.

이제 db/seeds.rb를 엽니다. 파일에 다음 코드를 추가하세요.

User.create(name: 'Luke Wan', age: 23, address: '123 Test St.')
User.create(name: 'Mary Poppins', age: 41, address: '123 ABC St.')
User.create(name: 'John Neilman', age: 76, address: '000 Test St.')

이 코드는 Users를 초기화합니다. 시작 시 일부 데이터가 있는 테이블. 저장하고 다음 명령을 실행합니다.

rake db:seed

이렇게 하면 위에 나열된 명령을 통해 테이블이 시드됩니다. 다음으로 SQLite 데이터베이스를 입력하고 다음 명령을 실행하여 작동하는지 확인할 수 있습니다.

sqlite3 db/development.sqlite3

그런 다음 테이블 데이터를 선택합니다.

select * from users;

결과를 볼 수 있습니다.

사용자 구성 요소

HTML과 CSS를 Rails 페이지로 변환하는 데 도움이 되도록 종속성을 몇 개 더 설치해야 합니다. Angular 라우터, Forms libs 및 ngx-bootstrap을 추가하여 Bootstrap 구성 요소의 생성 및 조작을 용이하게 하는 데 사용할 것입니다. 따라서 다음 명령을 실행하십시오.

yarn add @angular/router @angular/forms html-loader css-loader ngx-bootstrap

그러나 구성 요소 코드로 넘어가기 전에 Angular 구성 요소의 구조부터 시작하여 몇 가지 중요한 개념을 지적해야 합니다.

구성요소란 무엇입니까?

Angular에는 보기를 TypeScript로 만든 응용 프로그램 논리와 연결하는 구성 요소가 있습니다.

즉, 구성 요소는 보기가 기능을 지원하는 데 필요한 모든 논리의 컨테이너와 같습니다. 뷰가 표시하고 흐름을 제어하는 ​​값을 정의합니다. 유사한 프레임워크의 '컨트롤러'에 해당합니다.

구성 요소를 만들려면 새 클래스를 정의하고 OnInit 인터페이스를 만들고 클래스에 @Component 주석을 추가합니다. 데코레이터:

export class UserIndexComponent implements OnInit {
    constructor() { ... }

    ngOnInit() { ... }
}

@Component 및 OnInit

@Component 데코레이터는 이 클래스를 인식 가능한 Angular 구성 요소로 표시하고 런타임 중 처리, 인스턴스화 및 사용과 관련하여 Angular가 처리하는 데 도움이 되는 메타데이터 구성을 제공하기 때문에 중요합니다.

다음 메타데이터 구성을 사용합니다.

@Component({
    selector: "users",
    template: templateString,
})

여기, selector 제공된 값이 현재 지시문을 템플릿으로 식별하는 데 사용할 수 있는 CSS 선택기임을 Angular에 알려줍니다. 예, 다음 메타데이터 속성에서 제공되는 동일한 템플릿입니다.

OnInit 그러나 인터페이스는 선택 사항이며 구성 요소의 수명 주기가 완료되기 전에 항목을 초기화하는 좋은 방법입니다. 구성 후 방법처럼 작동합니다.

종속성 주입

Angular는 DI입니다(종속성 주입 ) 프레임워크, 모듈성과 생산성을 높이는 특성입니다.

Angular의 종속성은 서비스 및 리포지토리에서 코드의 다른 위치에 삽입하기에 적합하다고 생각되는 모든 종류의 일반 객체에 이르기까지 다양할 수 있습니다.

클래스를 "주사 가능"으로 바꾸려면 @Injectable로 주석만 추가하면 됩니다. 데코레이터:

@Injectable({
    providedIn: "root",
})
export class UserService {
    ...
}

providedIn 어떤 인젝터가 생성 중인 인젝터를 제공할 것인지 나타냅니다. root 값은 인젝터가 애플리케이션 수준의 인젝터여야 함을 Angular에 알려줍니다. 여기에서 더 확인할 수 있습니다.

예를 들어 클래스를 구성 요소에 삽입하려면 구성 요소의 생성자에서 수행하도록 Angular에 요청합니다.

constructor(
    private userService: UserService,
) {}

간단합니다!

완성된 구성 요소

아래에서 사용자 구성 요소에 대한 최종 코드 목록을 찾을 수 있습니다. index.component.ts에 배치합니다. , javascript/hello_angular/app/ 아래 폴더.

import { Component, OnInit, TemplateRef } from "@angular/core";
import { FormGroup, FormBuilder } from "@angular/forms";
import { BsModalRef, BsModalService } from "ngx-bootstrap/modal";

import templateString from "./index.component.html";
import { UserService } from "../user.service";
import { User } from "../user.class";

@Component({
  selector: "users",
  template: templateString,
})
export class UserIndexComponent implements OnInit {
  users: User[];
  modalRef: BsModalRef;
  userForm: FormGroup;
  isNew: Boolean;

  constructor(public fb: FormBuilder, private userService: UserService, private modalService: BsModalService) {}

  public newUser(template: TemplateRef<any>) {
    this.reset();
    this.modalRef = this.modalService.show(template);
  }

  public createUser() {
    this.userService.create(this.userForm.value).subscribe(() => {
      console.log("User created!");
      this.reset();

      this.modalRef.hide();
    });
  }

  public editUser(user, template: TemplateRef<any>) {
    this.isNew = false;
    this.userForm = this.fb.group({
      id: [user.id],
      name: [user.name],
      age: [user.age],
      address: [user.address],
    });

    this.modalRef = this.modalService.show(template);
  }

  public updateUser() {
    const { id } = this.userForm.value;
    this.userService.update(id, this.userForm.value).subscribe(() => {
      console.log("User updated!");
      this.reset();

      this.modalRef.hide();
    });
  }

  public deleteUser(id) {
    if (confirm("Are you sure?")) {
      this.userService.delete(id).subscribe(() => {
        console.log("User deleted!");
        this.reset();
      });
    }
  }

  ngOnInit() {
    this.reset();
  }

  public reset() {
    this.isNew = true;
    this.userService.getUsers().subscribe((users) => {
      this.users = users;
    });

    this.userForm = this.fb.group({
      id: [""],
      name: [""],
      age: [""],
      address: [""],
    });
  }
}

Users 배열은 화면에 나열된 현재 테이블 데이터를 보유하고 reset에서 검색합니다. UserService를 통해 Rails API를 호출하는 메소드 (만들 예정).

userForm 두 작업에 동일한 양식이 사용되므로 사용자를 만들고 업데이트하는 데 도움이 되는 참조일 뿐입니다. isNew 또한 현재 우리가 어떤 흐름에 있는지 식별하는 데 도움이 됩니다.

여기에서는 각 작업에 대해 CRUD에 해당하는 방법이 있습니다. 그들 각각은 각각의 UserService를 호출합니다. Rails API에서 프로세스를 커밋하는 메소드입니다.

또한 템플릿을 HTML로 변환하기 위해 HTML 모듈을 설정해야 합니다(모듈에 대한 자세한 내용은 곧 볼 예정입니다). 따라서 html.d.ts를 엽니다. 같은 폴더 안에 파일을 추가하고:

declare module "*.html" {
  const content: string;
  export default content;
}

Angular 서비스 및 모델

Angular의 UserService로 넘어갑시다. 창조. Angular는 Rails와 같은 프레임워크입니다. 따라서 예를 들어 중복(또는 매우 유사한) 모델이 있는 경우에도 규칙을 준수해도 된다는 의미입니다.

모델이란 무엇입니까?

Angular 모델은 함께 의미가 있는 데이터 속성을 보유하는 단순한 객체입니다(즉, 도메인의 간결한 부분을 나타냄). 대부분의 언어 및 프레임워크의 다른 모델과 같습니다.

사용자 모델과 같이 코드 전체에 데이터를 복제하는 것보다 데이터를 한 곳에 집중시키는 것이 많은 도움이 됩니다.

export class User {
  constructor(public id: number, public name: string, public age: number, public address: string) {}
}

TypeScript이므로 모델의 속성에는 항상 유형이 정의되어 있어야 합니다.

user.class.ts라는 새 파일을 만듭니다. javascript/hello_angular/app/user/ 아래 폴더에 위의 코드를 넣으세요.

서비스는 어떻습니까?

서비스는 광범위한 개념이지만 잘 정의되고 목적이 있는 개체로 이해할 수 있습니다. 일반적으로 외부 서비스나 데이터베이스에서 가져온 처리되고 변환된 데이터를 제공하여 더 복잡한 논리로 구성 요소를 돕습니다.

서비스에는 특정 주석이나 인터페이스가 필요하지 않습니다. 클래스를 만들고 주사 가능하게 만들기만 하면 됩니다. , 우리가 전에 본 것처럼. 그런 다음 구성 요소에 삽입할 수 있습니다.

관찰 가능한 서비스

Angular의 또 다른 흥미로운 기능은 클래스와 함께 RxJS를 사용할 수 있다는 것입니다.

예를 들어 Angular의 기본 HTTP 클라이언트는 외부 서비스에서 정보를 가져오는 데 사용하는 것과 동일하며 RxJS Observables를 반환합니다. . 그렇기 때문에 UserService 사용자 구성 요소 내에서 메소드를 subscribe할 수 있습니다. Observable 결과:

this.userService.getUsers().subscribe((users) => {
  this.users = users;
});

RxJS에 익숙하지 않다면 해당 문서를 간략하게 읽어보는 것이 좋습니다. 그렇게 어렵지 않습니다!;)

다시 말하지만, javascript/hello_angular/app/user/ 폴더에서 user.service.ts라는 다른 파일을 만듭니다. . 내용은 다음과 같습니다.

import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { map } from "rxjs/operators";
import { Observable } from "rxjs";

import { User } from "./user.class";

@Injectable({
  providedIn: "root",
})
export class UserService {
  constructor(private http: HttpClient) {}

  httpOptions = {
    headers: new HttpHeaders({
      "Content-Type": "application/json",
    }),
  };

  getUsers(): Observable<User[]> {
    return this.http.get("/users.json").pipe(
      map((users: User[]) =>
        users.map((user) => {
          return new User(user.id, user.name, user.age, user.address);
        })
      )
    );
  }

  create(user): Observable<User> {
    return this.http.post<User>("/users.json", JSON.stringify(user), this.httpOptions);
  }

  update(id, user): Observable<User> {
    return this.http.put<User>("/users/" + id + ".json", JSON.stringify(user), this.httpOptions);
  }

  delete(id) {
    return this.http.delete<User>("/users/" + id + ".json", this.httpOptions);
  }
}

이 구성 요소와 방금 만든 구성 요소 간의 유사점을 찾을 수 있습니까? 이는 구성 요소의 작업을 지원하기 위해 해당 작업이 필요하기 때문입니다.

HttpClient 또한 클래스의 생성자 내에 주입되어야 하므로 클래스와 함께 사용할 수 있습니다.

각 작업은 자동 생성된 Rails API에 대한 HTTP 호출을 수행합니다.

조회수

Angular는 보기용 템플릿과 함께 작동합니다. 템플릿은 Angular에 각 구성 요소를 렌더링하는 방법을 알려주는 일종의 계층적 HTML 및 JavaScript 혼합입니다.

그러나 뷰 구성을 더 진행하기 전에 먼저 Angular가 템플릿 시스템을 분할하는 방법을 이해합시다.

각도 지시문

Angular 템플릿은 본질적으로 동적이기 때문에 일부 지시문 Angular를 올바른 방식으로 렌더링하는 데 필요합니다.

지시문은 단순히 @Directive가 있는 클래스입니다. 구성 요소와 같은 데코레이터. 예, @Component @Directive에서 상속 , 그래서 공식적으로도 지시문입니다.

그러나 두 가지 다른 유형이 있습니다. 구조적속성 지시.

구조 지침

이러한 지시문은 JavaScript에서 Angular 템플릿으로 변환된 조건부 및 루프 구조를 나타냅니다. 그것들은 마치 바닐라 JavaScript 코드 내에서 프로그래밍하는 것처럼 템플릿을 최대한 동적으로 만드는 데 도움이 됩니다. 다음 예를 들어보세요.

<tr *ngFor="let user of users">
  <td>{{ user.name }}</td>
</tr>

*ngFor 지시문은 Angular에 users 배열을 반복하도록 지시합니다. DOM에 각 사용자의 이름을 인쇄합니다.

속성 지시문

이들은 요소의 모양이나 동작과 직접적으로 작동합니다. 다음 예를 들어보세요.

<form [formGroup]="userForm" (ngSubmit)="isNew ? createUser() : updateUser()" novalidate></form>

여기에서는 submit를 조건부로 설정하여 양식의 동작을 수정합니다. 기능 및 Angular의 FormGroup 사용 각 양식 입력을 데이터 바인딩합니다.

데이터 바인딩

웹 프레임워크로 양식을 만드는 것은 데이터 바인딩을 제공하지 않는 경우 까다롭고 오류가 발생하기 쉬운 작업이 될 수 있습니다.

Angular는 양방향 데이터 바인딩을 지원하므로 템플릿의 일부를 구성 요소에 직접 연결할 수 있으며 그 반대의 경우도 마찬가지입니다.

위의 양식은 FormGroup의 좋은 예입니다. 데이터 바인딩 능력. 각 양식 필드를 userForm에 자동으로 바인딩합니다. 구성 요소 내에서 생성된 개체입니다.

editUser에서 예를 들어, userForm 의 값은 구성 요소 내에서 설정되며 보기에 양식을 반영해야 합니다.

색인 보기 작성

index.component.html의 콘텐츠를 분석해 보겠습니다. 두 부분으로. 이것이 첫 번째 것입니다:

<div class="container pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
  <h1 class="display-4">User's Listing</h1>
  <p class="lead">A quick CRUD example of how to integrate Rails with Angular</p>

  <table class="table">
    <tr>
      <th>Id</th>
      <th>Name</th>
      <th>Age</th>
      <th>Address</th>
      <th>Actions</th>
    </tr>

    <tbody>
      <tr *ngFor="let user of users">
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
        <td>{{ user.address }}</td>
        <td colspan="2">
          <button class="btn btn-secondary" (click)="editUser(user, template)">Edit</button>
          |
          <button class="btn btn-danger" (click)="deleteUser(user.id)">Delete</button>
        </td>
      </tr>
    </tbody>
  </table>

  <button class="btn btn-primary float-right mt-4" (click)="newUser(template)">Insert New</button>
</div>

대부분이 일반 HTML로 구성되어 있습니다. Bootstrap 클래스에 대해서는 자세히 다루지 않겠습니다.

여기서 중요한 부분은 ngFor입니다. 테이블의 행에 대한 지시문. Users를 반복하는 데 도움이 됩니다. 배열(기억하시나요?) 각 속성을 {{ … }}를 통해 HTML 출력으로 인쇄 연산자.

onClick과 같은 DOM 이벤트 중 하나를 추가하고 싶을 때마다 , 이벤트 이름을 괄호로 묶고 클릭할 때 호출할 구성 요소 함수를 추가하기만 하면 됩니다.

모달 보기 만들기

두 번째 부분은 모달 내용과 관련이 있으므로 이전 부분 아래에 추가합니다.

<ng-template #template>
  <div class="modal-header">
    <h4 class="modal-title pull-left">{{ isNew ? "New User" : "Update User" }}</h4>
    <button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <form [formGroup]="userForm" (ngSubmit)="isNew ? createUser() : updateUser()" novalidate>
      <input type="hidden" formControlName="id" class="form-control" />
      <div class="form-group">
        <label>Name</label>
        <input type="text" formControlName="name" class="form-control" />
      </div>
      <div class="form-group">
        <label>Age</label>
        <input type="text" formControlName="age" class="form-control" />
      </div>
      <div class="form-group">
        <label>Address</label>
        <textarea class="form-control" formControlName="address" rows="3"></textarea>
      </div>

      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>
</ng-template>

<ng-template> HTML과 Angular 사이에 요소를 고정할 수 있는 태그입니다. 템플릿 ID는 # 바로 뒤에 옵니다. 서명.

양식 내에서 isNew 이 양식의 현재 사용이 사용자의 생성 또는 업데이트와 관련이 있는지 여부를 확인하기 위한 구성 요소 변수입니다.

마지막으로 전체 hello_angular를 주입해야 합니다. Rails index.html.erb에 애플리케이션 페이지. 따라서 views/users/ 아래에서 이 파일을 엽니다. 폴더의 내용을 다음과 같이 변경합니다.

<hello-angular>We're almost done...</hello-angular> <%= javascript_pack_tag 'hello_angular' %>

각도 모듈

이제 우리는 Angular에게 물건을 찾을 위치를 알려야 합니다. 모듈의 구성 내에서 발생합니다.

먼저 app-bootstrap.module.ts에 콘텐츠를 추가해 보겠습니다. :

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";

import { ModalModule } from "ngx-bootstrap/modal";

@NgModule({
  imports: [CommonModule, ModalModule.forRoot()],
  exports: [ModalModule],
})
export class AppBootstrapModule {}

이것은 ngx-bootstrap에서 상속받은 Bootstrap 구성 요소로 제한됩니다. 현재 사용하고 있는 유일한 구성 요소는 Bootstrap 모달입니다.

그런 다음 app-routing.module.ts를 엽니다. 파일의 내용을 다음과 같이 변경합니다.

import { RouterModule, Routes } from "@angular/router";
import { NgModule } from "@angular/core";

import { UserIndexComponent } from "./user/index/index.component";

const appRoutes: Routes = [
  { path: "users", component: UserIndexComponent },
  { path: "", redirectTo: "/users", pathMatch: "full" },
];

@NgModule({
  imports: [RouterModule.forRoot(appRoutes, { scrollPositionRestoration: "enabled" })],
  exports: [RouterModule],
})
export class AppRoutingModule {}

이렇게 하면 /users 경로가 호출됩니다.

마지막으로 기본 AppModule 내에 모두 등록합니다. 수업. app.module.ts를 엽니다. 파일을 만들고 다음과 같은지 확인하십시오.

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { HttpClientModule } from "@angular/common/http";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";

import { AppComponent } from "./app.component";
import { AppRoutingModule } from "./app-routing.module";
import { AppBootstrapModule } from "./app-boostrap.module";
import { UserIndexComponent } from "./user/index/index.component";

@NgModule({
  declarations: [AppComponent, UserIndexComponent],
  imports: [HttpClientModule, AppRoutingModule, BrowserModule, FormsModule, ReactiveFormsModule, AppBootstrapModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

여기 모든 것이 매핑되어 있습니다. 우리의 양식, HTTP 클라이언트 및 사용자 구성 요소에서 부트스트랩 모듈 구성 및 라우팅까지.

구성 완료

테스트를 시작하기 전에 app.component.ts부터 시작하여 몇 가지 작업을 완료해야 합니다. 파일:

import { Component } from "@angular/core";

@Component({
  selector: "hello-angular",
  template: "<router-outlet></router-outlet>",
})
export class AppComponent {
  name = "Angular!";
}

기본 앱 구성 요소는 경로를 라우팅하는 방법을 알아야 하므로 RouterOutlet이 작업을 수행합니다.

그런 다음 Webpacker가 지금까지 작업 중인 HTML 확장을 이해하는지 확인해야 합니다. 이를 위해 webpacker.yml을 엽니다. 파일 및 /config 아래 폴더에서 확장자를 검색합니다. 섹션에 다음 항목을 추가하십시오.

- .html

Webpacker는 기본적으로 Angular와 함께 제공되는 내장 TypeScript 로더만 인식합니다. HTML을 처리해야 하므로 이전에 html-loader를 설치했습니다. 의존. 설정하려면 environment.js를 엽니다. 파일, config/webpack 아래 폴더에 다음 로더 구성을 추가합니다.

environment.loaders.append("html", {
  test: /\.html$/,
  use: [
    {
      loader: "html-loader",
      options: {
        minimize: true,
      },
    },
  ],
});

마지막으로 Angular 서비스가 HTTP 호출에서 오류를 수신하지 못하도록 하려면 Rails에서 수행하는 CSRF 토큰 검사를 비활성화해야 합니다. 이를 위해 application_controller.rb를 엽니다. 파일, 앱/컨트롤러 아래 폴더의 내용을 다음과 같이 변경합니다.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
end

테스트

그게 다야! 설정에 많은 사용자 지정이 필요하기 때문에 약간 까다로워 보이지만 결과는 그만한 가치가 있습니다.

테스트하려면 모든 것을 저장하고 rails s를 실행하여 서버를 시작하십시오. 명령.

그런 다음 웹 브라우저로 이동하여 주소 https://localhost:3000/users를 입력합니다. CRUD 웹 애플리케이션을 사용해 보세요.

결론

이 CRUD를 시작하고 실행하는 것은 긴 여정이었습니다. 첫 번째 시도 후에는 향후 프로젝트에 대한 작업이 더 쉬워지는 것을 알 수 있습니다. 이 프로젝트가 두 기술에 합류하여 프로젝트를 빠르게 시작하려는 사람들에게 시작점을 설정하는 데 도움이 되길 바랍니다.

우리는 그것을 도울 오픈 소스 스캐폴딩 프로젝트가 없지만 그런 자료를 갖기 위해 서로의 노력에 의존합니다. 이제 당신 차례입니다. 프로젝트를 포크(또는 처음부터 생성)하고 사용자 정의를 시작하십시오.

이 예제의 GitHub 리포지토리는 여기에서 찾을 수 있습니다. 즐거운 시간 보내세요!