Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

Angular को Rails 5 के साथ इंटीग्रेट करना: एक सहज फुल-स्टैक दृष्टिकोण

आपने पहले कहानी सुनी है। आपके पास पहले से ही एक एप्लिकेशन है जो आपके विकेंद्रीकृत और पूरी तरह से काम करने वाले बैक-एंड APIs और किसी सामान्य टूलसेट के साथ बने फ्रंट-एंड पर चल रहा है।

अब, आप Angular पर आगे बढ़ना चाहते हैं। या, शायद आप बस अपने रेल्स प्रोजेक्ट्स के साथ Angular को इंटीग्रेट करने का एक तरीका ढूंढ रहे हैं क्योंकि आप चीजों को इस तरह पसंद करते हैं। हम आपको दोष नहीं देते।

ऐसे दृष्टिकोण के साथ, आप दोनों दुनियाओं का लाभ उठा सकते हैं और तय कर सकते हैं कि आप चीजों को फॉर्मेट करने के लिए रेल्स या Angular से फीचर्स का उपयोग करना चाहते हैं, उदाहरण के लिए।

हम क्या बनाएंगे

चिंता करने की कोई जरूरत नहीं। यह ट्यूटोरियल इस उद्देश्य के लिए लिखा गया था। हम यूजर्स के डोमेन पर एक पूरी तरह से काम करने वाले CRUD एप्लिकेशन के निर्माण में गोता लगाएंगे।

लेख के अंत तक, आप Angular के चारों ओर कुछ बुनियादी अवधारणाओं को सीख चुके होंगे और एक रेल्स बैक-एंड प्रोजेक्ट सेट अप करने का तरीका जानेंगे जो फ्रंट-एंड के लिए Angular के साथ सीधे इंटीग्रेट होता है, जैसा कि नीचे दिखाया गया है:

Angular को Rails 5 के साथ इंटीग्रेट करना: एक सहज फुल-स्टैक दृष्टिकोण रेल्स और Angular के साथ बने यूजर्स का CRUD

एप्लिकेशन एक बाहरी फेक-टेस्टिंग वेब सर्विस से प्राप्त यूजर्स के डोमेन पर सभी चार CRUD ऑपरेशंस को संभालेगा। ऐप एक MVC आर्किटेक्चर के शीर्ष पर बनाया जाएगा, जिसमें प्रत्येक Angular लेयर को विस्तार से समझाया गया है ताकि आप बेहतर ढंग से समझ सकें कि चीजें कैसे एक साथ जुड़ती हैं। स्टाइल Bootstrap पर निर्भर है।

सेटअप

जैसा कि आपने अनुमान लगाया होगा, हमें निम्नलिखित सॉफ्टवेयर की आवश्यकता होगी:

  • रूबी (मैंने वर्जन 2.7.0preview1 चुना है),
  • रूबी और रेल्स (मैं इसके वर्जन 5.0.7.2 का उपयोग कर रहा हूं),
  • Node.js (मैं v13.7.0 के साथ जा रहा हूं),
  • Yarn (कम से कम इसका वर्जन 1.22.4)

सब कुछ ठीक से इंस्टॉल करना सुनिश्चित करें। फिर, हम प्रोजेक्ट पर आगे बढ़ सकते हैं। अपनी पसंद का एक फोल्डर चुनें और निम्नलिखित कमांड चलाएं:

rails new crud-rails-angular 

सेटअप पूरा होने की प्रतीक्षा करें और प्रोजेक्ट को अपने पसंदीदा IDE में खोलें। हम इस लेख के लिए VS Code के साथ काम करने जा रहे हैं क्योंकि यह सरल, शक्तिशाली है, और रेल्स और Angular दोनों सिंटैक्स को सहजता से अपनाता है।

यदि आप कुछ समय से रेल्स 5 का उपयोग कर रहे हैं, तो आपने देखा होगा कि इसका new कमांड SQLite कॉन्फिग के लिए Gemfile के भीतर एक बग उत्पन्न करता है। यह न्यूनतम वर्जन के बिना आता है, और इससे यह एरर्स के साथ चलेगा। आइए इस समस्या को इसे अपडेट करके ठीक करें

gem 'sqlite3', '~> 1.3.10' 

बिल्कुल सही!

Webpacker सेटअप

रेल्स में जावास्क्रिप्ट-जैसे एप्लिकेशंस को मैनेज करने का सबसे अच्छा तरीका Webpacker के माध्यम से है। यह पर्दे के पीछे Webpack का उपयोग करता है ताकि जावास्क्रिप्ट ऐप्स, जैसे Angular, को मौजूदा रेल्स एप्लिकेशन में प्री-प्रोसेसिंग और बंडलिंग जैसी सुविधाएं प्रदान की जा सकें।

इसे इंस्टॉल करने के लिए, बस अपने Gemfile में एक नई लाइन जोड़ें:

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

यह सुनिश्चित करेगा कि आप एक बहुत हालिया वर्जन इंस्टॉल करेंगे। अगला, निम्नलिखित कमांड चलाएं:

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

पहला कमांड जोड़े गए रेल्स निर्भरताओं को डाउनलोड और अपडेट करेगा।

दूसरा npm install के बराबर है क्योंकि यह node_modules फोल्डर बनाता है और Babel, Sass, Browserlist, और Webpack जैसी आवश्यक Angular निर्भरताओं का एक गुच्छा इंस्टॉल करता है। अब, हमारे पास एक ही प्रोजेक्ट में Node और रेल्स ऐप दोनों हैं।

नवीनतम कमांड में, हमारे पास npm install angular का समकक्ष है, जो सभी Angular-आवश्यक निर्भरताओं को डाउनलोड करेगा और इसे हमारे रेल्स प्रोजेक्ट के साथ काम करने देगा।

इन कमांड्स के अंत में, आप package.json फाइल को बने हुए भी देख सकते हैं। हमारी सभी आवश्यक निर्भरताएं वहां रखी गई हैं, और आप भविष्य में जो भी आवश्यकता हो जोड़ सकते हैं।

इसके अलावा, /app फोल्डर के तहत कुछ फोल्डर्स और फाइलें बनाई गईं, जैसे नया /javascript। इस फोल्डर में, आपके पास पहले से ही विकास की शुरुआत का समर्थन करने के लिए बनाया गया एक /hello_angular फोल्डर है।

कुछ समय बचाने के लिए, मैं आपसे अपने फोल्डर्स और फाइलों की संरचना को निम्नलिखित के साथ मिरर करने के लिए कहूंगा:

Angular को Rails 5 के साथ इंटीग्रेट करना: एक सहज फुल-स्टैक दृष्टिकोण

कुछ Angular समायोजन

Webpacker आपके जनरेटेड रेल्स प्रोजेक्ट के भीतर समायोजन की एक श्रृंखला की सिफारिश करता है। तो, आइए घर को व्यवस्थित करने में कुछ समय लें।

सबसे पहले, /packs फोल्डर के तहत रखी गई application.js फाइल खोलें (ऊपर की आकृति में दिखाया गया है) और निम्नलिखित कोड जोड़ें:

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

ये इम्पोर्ट्स रेल्स प्रोजेक्ट के भीतर जावास्क्रिप्ट एनवायरनमेंट को स्थिर करने के लिए एक सहायक बल के रूप में काम करते हैं।

अब, हमें रेल्स को यह बताने की आवश्यकता है कि उसे अपने पेजों का आउटपुट कहां से लेना चाहिए। एक बार Webpacker चीजों को पैक करना समाप्त कर देता है, यह रेल्स के बारे में जागरूक होने के लिए वितरण योग्य स्टेटिक फाइलों का एक गुच्छा जनरेट करेगा।

app/views/layout फोल्डर के तहत application.html.erb फाइल पर जाएं और इसके <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 टैग जोड़ रहे हैं, जो रेल्स को बताता है कि एप्लिकेशन स्टार्ट होने पर कहां देखना है।
  2. हम पेज पर स्टाइल का अनुमान लगाने के लिए Bootstrap का उपयोग करेंगे, ताकि हम केवल इम्प्लीमेंटेशन पर ध्यान केंद्रित कर सकें।
  3. यहां वह जगह है जहां आपको Webpacker टैग रखना होगा जो /packs फोल्डर कंटेंट पर मैप करता है (वही जो Webpacker द्वारा हर कंपाइलेशन के बाद ऑटो-जेनरेट किया जाएगा)।

मॉडल और डेटाबेस

डेटाबेस सेटअप पर आगे बढ़ें। चीजों को तेज करने के लिए, हम User नामक एक नया मॉडल स्कैफोल्ड करेंगे। इसे प्राप्त करने के लिए आपको निम्न कमांड चलाना होगा:

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

यह हमारे मॉडल के सभी फोल्डर्स और फाइलें बनाएगा, जिनकी हमें रेल्स को डेटाबेस जानकारी (SQLite से) में हेरफेर करने और इसे हमारे CRUD ऑपरेशंस में स्टोर करने के लिए आवश्यकता होगी।

फिर, आप देखेंगे कि db/migrate/ फोल्डर के तहत XXX1_create_users.rb नामक एक नई फाइल बनाई गई थी। इसे खोलें, और आप नए बनाए गए CreateUsers रिकॉर्ड को देखेंगे।

app/models/ फोल्डर के भीतर, आप user.rb फाइल पर तब बने User मॉडल को देखेंगे।

अब, 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 को हमारे रेल्स पेजेस में बदलने में मदद करने के लिए कुछ और निर्भरताओं को इंस्टॉल करने की आवश्यकता होगी; Angular राउटर, फॉर्म्स लिब्स, और 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 Angular को बताता है कि प्रदान किया गया मान CSS सेलेक्टर है जिसका उपयोग यह वर्तमान डायरेक्टिव को टेम्पलेट में पहचानने के लिए कर सकता है; हां, यह अगले मेटाडेटा प्रॉपर्टी में प्रदान किया गया वही टेम्पलेट है।

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 (बनाया जाने वाला) के माध्यम से हमारे रेल्स API को कॉल करता है।

userForm केवल एक रेफरेंस है जो हमारे यूजर्स को बनाने और अपडेट करने में मदद करता है क्योंकि वही फॉर्म दोनों ऑपरेशंस के लिए उपयोग किया जाएगा। isNew भी इसमें मदद करता है, यह पहचानता है कि हम वर्तमान में किस फ्लो में हैं।

यहां, हमारे पास प्रत्येक ऑपरेशन के लिए एक CRUD-समतुल्य मेथड है। उनमें से प्रत्येक प्रक्रिया को रेल्स API में कमिट करने के लिए संबंधित UserService मेथड को कॉल करता है।

हमें HTML मॉड्यूल को भी सेट अप करने की आवश्यकता होगी ताकि हमारे टेम्पलेट्स को HTML में बदला जा सके (हम जल्द ही मॉड्यूल्स पर अधिक देखेंगे)। तो, उसी फोल्डर के भीतर html.d.ts फाइल खोलें और जोड़ें:

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

Angular सर्विस और मॉडल

आइए Angular के UserService निर्माण पर आगे बढ़ें। Angular रेल्स की तरह एक फ्रेमवर्क है। तो, इसका मतलब है कि उनके नियमों का पालन करना ठीक है भले ही इसका मतलब डुप्लिकेट (या बहुत समान) मॉडल्स होना हो, उदाहरण के लिए।

मॉडल क्या है?

Angular मॉडल सरल ऑब्जेक्ट्स हैं जो डेटा एट्रिब्यूट्स को रखते हैं जो एक साथ समझ में आते हैं (यानी, वे आपके डोमेन के एक संक्षिप्त टुकड़े का प्रतिनिधित्व करते हैं)। वे अधिकांश लैंग्वेज और फ्रेमवर्क में किसी भी अन्य मॉडल की तरह हैं।

अपने डेटा को एक जगह पर केंद्रित करने में बहुत मदद मिलती है, बजाय इसे पूरे कोड में डुप्लिकेट करने के जैसे हम अपने यूजर के मॉडल के साथ करते हैं:

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

याद रखें कि यह TypeScript है, इसलिए आपके मॉडल के एट्रिब्यूट्स में हमेशा एक टाइप परिभाषित होना चाहिए।

javascript/hello_angular/app/user/ फोल्डर के तहत user.class.ts नामक एक नई फाइल बनाएं और ऊपर दिए गए कोड को इसमें रखें।

सर्विस के बारे में क्या?

सर्विसेज एक व्यापक अवधारणा है, लेकिन हम उन्हें अच्छी तरह से परिभाषित और उद्देश्यपूर्ण ऑब्जेक्ट्स के रूप में समझ सकते हैं। वे अधिक जटिल लॉजिक के साथ कंपोनेंट्स की मदद करते हैं, उन्हें प्रोसेस्ड और ट्रांसफॉर्म्ड डेटा के साथ सेवा प्रदान करते हैं, आमतौर पर एक एक्सटर्नल सर्विस या डेटाबेस से आते हैं।

एक सर्विस को किसी विशिष्ट एनोटेशन या इंटरफेस की आवश्यकता नहीं होती; आप बस एक क्लास बनाते हैं और इसे इंजेक्टेबल बनाते हैं, जैसा कि हमने पहले देखा है। फिर, आप इसे अपने कंपोनेंट्स में इंजेक्ट कर सकते हैं।

ऑब्जर्वेबल सर्विसेज

Angular की एक और दिलचस्प विशेषता यह है कि यह आपको RxJS को अपनी क्लासेस के साथ उपयोग करने की अनुमति देता है।

उदाहरण के लिए, Angular का डिफ़ॉल्ट HTTP क्लाइंट, वही जिसे हम एक्सटर्नल सर्विस से जानकारी प्राप्त करने के लिए उपयोग करेंगे, RxJS Observables वापस करता है। यही कारण है कि जब आप यूजर कंपोनेंट के भीतर हमारे किसी UserService मेथड को कॉल करते हैं, तो आप Observable परिणाम को subscribe कर सकते हैं:

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 को भी क्लास के कंस्ट्रक्टर के भीतर इंजेक्ट किया जाना चाहिए, ताकि हम इसे क्लास के साथ उपयोग कर सकें।

प्रत्येक ऑपरेशन हमारे रेल्स API, ऑटो-जेनरेटेड वाले पर एक HTTP कॉल करता है।

व्यूज

Angular अपने व्यूज के लिए टेम्पलेट्स के साथ काम करता है। एक टेम्पलेट एक प्रकार का हायरार्किकल HTML-और-जावास्क्रिप्ट मिश्रण है जो Angular को बताता है कि प्रत्येक कंपोनेंट को कैसे रेंडर करना है।

हालांकि, हमारे व्यू के निर्माण के साथ आगे बढ़ने से पहले, आइए पहले समझें कि Angular अपने टेम्पलेट सिस्टम को कैसे विभाजित करता है।

Angular डायरेक्टिव्स

क्योंकि Angular टेम्पलेट्स अनिवार्य रूप से डायनामिक हैं, कुछ डायरेक्टिव्स की आवश्यकता होती है जो Angular को सामान रेंडर करने के सही तरीके से चलाते हैं।

डायरेक्टिव्स बस @Directive डेकोरेटर वाली क्लासेस हैं, जैसे कंपोनेंट्स। हां, @Component @Directive से इनहेरिट करता है, इसलिए यह आधिकारिक तौर पर एक डायरेक्टिव भी है।

हालांकि, दो अन्य प्रकार हैं: स्ट्रक्चरल और एट्रिब्यूट डायरेक्टिव्स।

स्ट्रक्चरल डायरेक्टिव्स

ये डायरेक्टिव्स जावास्क्रिप्ट से Angular टेम्पलेट में अनुवादित सशर्त और लूप संरचनाओं का प्रतिनिधित्व करते हैं। वे टेम्पलेट को यथासंभव डायनामिक बनाने में मदद करते हैं, जैसे कि आप अपने वेनिला जावास्क्रिप्ट कोड के भीतर प्रोग्रामिंग कर रहे थे। निम्नलिखित उदाहरण लें:

<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 आउटपुट पर प्रिंट करता है।

जब भी आप DOM इवेंट्स में से एक जोड़ना चाहते हैं, जैसे onClick, बस इवेंट नाम को पैरेंथेसिस में लपेटें और कंपोनेंट फंक्शन जोड़ें जिसे यह क्लिक होने पर कॉल करेगा।

मोडल व्यू बनाना

दूसरा भाग मोडल कंटेंट से संबंधित है, इसलिए इसे पिछले वाले के नीचे जोड़ें:

<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 एप्लिकेशन को रेल्स index.html.erb पेज में इंजेक्ट करने की आवश्यकता है। तो, views/users/ फोल्डर के तहत इस फाइल को खोलें और इसकी सामग्री को निम्नानुसार बदलें:

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

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 {} 

यह सुनिश्चित करेगा कि Angular सही यूजर कंपोनेंट से मेल खाता है जब /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 क्लाइंट और यूजर कंपोनेंट से Bootstrap मॉड्यूल कॉन्फिग्स, और रूटिंग तक।

कॉन्फिग्स को पूरा करना

टेस्ट में कूदने से पहले, हमें कुछ चीजों को पूरा करने की आवश्यकता है, 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 फोल्डर के तहत, extensions सेक्शन खोजें और निम्नलिखित आइटम जोड़ें:

- .html 

Webpacker केवल बिल्ट-इन TypeScript लोडर को पहचानता है जो Angular के साथ डिफ़ॉल्ट रूप से आता है। हमें HTML को प्रोसेस करने की आवश्यकता है, यही कारण है कि हमने पहले html-loader निर्भरता इंस्टॉल की थी। इसे सेट अप करने के लिए, config/webpack फोल्डर के तहत environment.js फाइल खोलें, और निम्नलिखित लोडर कॉन्फिग जोड़ें:

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

अंत में, हमारे Angular सर्विस को उनके HTTP कॉल्स पर एरर्स प्राप्त करने से रोकने के लिए, हमें रेल्स द्वारा किए जाने वाले CSRF टोकन चेक्स को अक्षम करने की आवश्यकता है। इसके लिए, app/controllers फोल्डर के तहत application_controller.rb फाइल खोलें, और इसकी सामग्री को निम्नानुसार बदलें:

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

टेस्टिंग

बस! यह थोड़ा ट्रिकी लगता है क्योंकि सेटअप के लिए बहुत सारे कस्टमाइजेशन की आवश्यकता होती है, लेकिन परिणाम इसके लायक है।

टेस्ट करने के लिए, सब कुछ सेव करें, और rails s कमांड जारी करके सर्वर शुरू करें।

फिर, अपने वेब ब्राउज़र पर जाएं और एड्रेस https://localhost:3000/users टाइप करें। आगे बढ़ें और CRUD वेब एप्लिकेशन के साथ खेलें।

निष्कर्ष

इस CRUD को चालू और चालू रखने के लिए यह एक लंबा रास्ता रहा है। पहले ट्रायल के बाद, आप देखेंगे कि चीजें आपके भविष्य के प्रोजेक्ट्स के लिए आसान हो जाती हैं। मुझे आशा है कि यह प्रोजेक्ट उन लोगों के लिए एक प्रारंभिक बिंदु स्थापित करने में मदद करता है जो दोनों टेक्नोलॉजीज को जोड़कर जल्दी से एक प्रोजेक्ट शुरू करना चाहते हैं।

जबकि हमारे पास इसके साथ मदद करने के लिए एक ओपन-सोर्स स्कैफोल्डिंग प्रोजेक्ट नहीं है, हम एक-दूसरे के प्रयासों पर भरोसा करते हैं ताकि ऐसी सामग्री हो। अब, आपकी बारी है; प्रोजेक्ट को फोर्क करें (या इसे स्क्रैच से बनाएं) और अपने कस्टमाइजेशन बनाना शुरू करें।

इस उदाहरण के लिए GitHub रिपॉजिटरी यहां पाई जा सकती है। मजा करें!


  1. अपने Rails एप्लिकेशन में DynamoDB का लाभ उठाएं अपने Rails एप्लिकेशन में DynamoDB का लाभ उठाएं

    इसके मूल में, DynamoDB एक NoSQL डेटाबेस है जो की-वैल्यू और डॉक्यूमेंट डेटा संरचनाएं प्रदान करता है। आइए इसे अनपैक करें। मुझे लगता है कि इसे पढ़ने वाले अधिकांश डेवलपर्स पारंपरिक रिलेशनल डेटाबेस सिस्टम से काफी परिचित हैं, जिनमें अच्छी तरह से परिभाषित स्कीमा और डेटा शामिल होते हैं जो टेबल्स, पंक्तियों

  1. Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग

    यदि आप पेज परिवर्तनों और फॉर्म सबमिशन को तेज़ करने और जटिल पेज को बिना कोई JavaScript कोड लिखे घटकों में विभाजित करने का तरीका ढूंढ रहे हैं, तो यह पोस्ट आपको Hotwire के साथ Rails को अगले स्तर पर ले जाने में मदद करेगी। यह लेख आपको सर्वर-साइड रेंडरिंग के लिए एक टूल का उपयोग करना सिखाएगा। Hotwire क्या

  1. रूबी ऑन रेल्स में टेलविंड CSS जोड़ें: एक व्यावहारिक चरण-दर-चरण गाइड रूबी ऑन रेल्स में टेलविंड CSS जोड़ें: एक व्यावहारिक चरण-दर-चरण गाइड

    CSS जादुई है लेकिन समय लेने वाला। सुंदर, कार्यात्मक, और सुलभ साइट्स उपयोग करने में आनंददायक हैं, लेकिन अपना खुद का CSS लिखना थकाऊ है। कई CSS लाइब्रेरी, जैसे बूटस्ट्रैप, हाल के वर्षों में विस्फोट हुए हैं, और टेलविंड 2021 में पैक का नेतृत्व कर रहा है। हालांकि रेल्स टेलविंड के साथ बॉक्स से बाहर नहीं आ