برنامه نویسی سایت نظرسنجی مشابه سایت reddit - بخش ۱-۵

13 آذر 1395
angular2main

در بخش ۱-۴ پس از بررسی سیستم انگولار ۲ و چگونگی کارکرد آن، نوشتن نرم افزار تحت‌ وب نظرسنجی مشابه سایت reddit را آغاز کردیم. در نهایت یک کامپوننت و قالب مشخص برای ثبت نام و لینک مطلب موردنظر ایجاد و آن را به تفصیل شرح دادیم. حال در این بخش به ادامه‌ی مسیر طراحی و برنامه‌نویسی سایت نظرسنجی می‌پردازیم. با ما همراه باشید.

اضافه کردن کامپوننت مطالب

هم‌اکنون ما فرمی برای ثبت نام و لینک مطلب موردنظر داریم، اما جدیدترین مطالب قابل مشاهده نیستند. برای اینکار یک کامپوننت جدید با نام article ایجاد می‌کنیم:

ng generate component article

سه بخش اصلی را برای این کامپوننت درنظر میگیریم:

  1. تعریف view کامپوننت ArticleComponent در template
  2. تعریف ویژگی‌های ArticleComponent توسط مفسرهای @Component
  3. تعریف کلاس ArticleComponent جهت ایجاد دستورهای منطقی

تمام قسمتهای فوق را به تفصیل شرح می‌دهیم:

ایجاد قالب ArticleComponent

قالب اصلی خود را در فایل article.component.html اضافه می‌کنیم، مجددا یادآور می‌شویم که ما در این پروژه از فریم‌ورک CSS بوت استراپ استفاده کرده‌ایم:

<div class="row">
  <div class="col-md-3 text-center">
    <a href (click)="voteUp()"><i class="fa fa-arrow-up"></i></a>
    <a href (click)="voteDown()"><i class="fa fa-arrow-down"></i></a>
  </div>
  <div class="col-md-3 text-center"><a href="{{ article.link }}"> {{ article.title }} </a></div>
  <div class="col-md-3 text-center"><a href="{{ article.link }}"> {{ article.link }} </a></div>
  <div class="col-md-3 text-center"><span class="badge bg-red">{{ article.votes }}</span></div>
</div>

با مطالعه‌ی کد بالا با یک سری دستور روبه‌رو خواهید شد. برای زیباتر شدن فرم نظردهی مطالب، از یک جدول با چهار ستون استفاده کرده‌ایم که ستون‌های آن شامل امتیازدهی، عنوان مطلب، لینک مطلب و امتیاز می‌باشد. درون ستون امتیاز دهی از دو دکمه فلش بالا و پایین برای افزایش و کاهش امتیاز استفاده کرده‌ایم که این دو فلش دو تابع voteup() و votedown() را فراخوانی می‌کنند. همچنین در ستون امتیاز نیز مقدار امتیاز را با متغییر votes نمایش می‌دهیم. از طرفی عناوین و لینک‌های مطالب را در متغییرهای link و title قرار داده‌ایم.

ایجاد کلاس ArticleComponent

به مسیر article.component.ts‌ رفته و کلاس ArticleComponent را تعریف می‌کنیم:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
  votes: number;
  title: string;
  link: string;

  constructor() {
    this.title = "Roxo Online Tutorials";
    this.link = "http://www.roxo.ir";
    this.votes = 10;
  }

  voteUp(){
    this.votes += 1;
  }

  voteDown(){
    this.votes -= 1;
  }

  ngOnInit() {
  }

}

در اینجا سه ویژگی اصلی ایجاد شده است:

  1. votes که شامل مجموعه‌ی تمام upvotes و downvotesها می‌باشد.
  2. title که برای نگه‌داری عنوان مطالب مورد استفاده قرار می‌گیرد.
  3. link که برای نگه‌داری لینک مطالب مورد استفاده قرار می‌گیرد.

سازنده‌ی پیش‌فرض این کلاس نیز دارای صفاتی است:

  1. this.title برابر مقدار Roxo Online Tutorials
  2. this.link برابر مقدار http://www.roxo.ir
  3. this.votes برابر مقدار عددی ۱۰

و در انتها دو تابع به نام‌های voteUp و voteDown جهت افزایش و کاهش مقادیر امتیاز مورد استفاده قرار می‌گیرد.

استفاده از کامپوننت app-article

جهت استفاده از این کامپوننت باید تگ <app-article></app-article> را در فایل اصلی AppComponent فراخوانی کنید. برای اینکار فایل app.component.html را باز کرده و تگ فوق را به انتهای فرم خود اضافه کنید. بنابراین داریم:

<div class="row">
<!-- Horizontal Form -->
  <div class="col-md-8 col-center-block">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت لینک</h3>
      </div>
      <!-- /.box-header -->
      <!-- form start -->
      <form class="form-horizontal">
        <div class="box-body">
          <div class="form-group">
            <label for="title" class="col-sm-2 control-label">عنوان مطلب</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="title" placeholder="عنوان مطلب خود را وارد کنید" #newtitle>
            </div>
          </div>
          <div class="form-group">
            <label for="link" class="col-sm-2 control-label">لینک</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="link" placeholder="لینک مطلب را وارد کنید" #newlink>
            </div>
          </div>
        </div>
        <!-- /.box-body -->
        <div class="box-footer">
          <button type="submit" (click)="addArticle(newtitle, newlink)"  class="btn btn-info pull-right">ثبت</button>
        </div>
        <!-- /.box-footer -->
      </form>
    </div>

    <div class="box">
      <div class="box-header">
        <h3 class="box-title">نظرسنجی مطالب</h3>
      </div>
      <!-- /.box-header -->
      <div class="box-body no-padding">
        <div class="row">
            <div class="col-md-3 text-center">امتیازدهی</div>
            <div class="col-md-3 text-center">عنوان مطلب</div>
            <div class="col-md-3 text-center">لینک مطلب</div>
            <div class="col-md-3 text-center">مجموع امتیازها</div>
        </div>
          <app-article></app-article>


      </div>
      <!-- /.box-body -->
    </div>
    <!-- /.box -->

  </div>
  </div>
  <!-- /.box -->

چنانچه شما صفحه اصلی خود را بروزرسانی کنید باید تصویر زیر را مشاهده کنید:

فرم ثبت اطلاعات نظرسنجی

علی‌رغم اینکه شما توابع را مورد استفاده قرار داده‌اید با کلیک کردن روی فلش‌های بالا و پایین علاوه بر اضافه یا کم شدن امتیاز، صفحه بروزرسانی یا به اصطلاح refresh می‌شود. جاوا اسکریپت به صورت پیش‌فرض، رویداد click را برای تمامی کامپوننت‌های والد فعال نگه می‌دارد. زیرا رویداد click یک انتشار برای والد می‌باشد. بنابراین مرورگر ما تلاش می‌کند تا یک لینک خالی را دنبال کند و در نهایت صفحه مرورگر مجددا بروزرسانی یا refresh می‌شود.

برای حل این مشکل باید رویداد click را طوری طراحی کنیم که مقدار false را باز گرداند. این مقدار به مرورگر می‌گوید که صفحه را بروزرسانی نکن! بنابراین کدهای موجود در توابع voteUp و voteDown را بروزرسانی می‌کنیم و علاوه بر انجام فرآیند افزایش یا کاهش امتیاز یک نوع boolean با مقدار false را بر می‌گردانیم. بنابراین داریم:

  voteUp(){
    this.votes += 1;
    return false;
  }

  voteDown(){
    this.votes -= 1;
    return false;
  }

خروجی گرفتن برای چندین ردیف مطلب

هم‌اکنون ما تنها یک ردیف با مقدار پیش‌فرض در جدول خود داریم و هیچ راهی برای افزودن سایر مطالب وجود ندارد. و اگر بخواهیم چندین ردیف داشته باشیم باید ده‌ها بار تگ <app-article> را کپی کنیم که در این شرایط یک مقدار ۱۰ بار برای هر سطر کپی می‌شود و اصلا جنبه خوبی ندارد. بنابراین باید یک کلاس تحت عنوان Article ایجاد کنیم.

ساخت کلاس Article

یکی از راه‌های عملی و زیبا برای کدنویسی در انگولار ۲، ایزوله کردن ساختار داده‌ها با استفاده از ایجاد کلاس در کامپوننت‌هاست. برای انجام این کار یک ساختار داده ایجاد کرده که یک مطلب تکی را نمایش می‌دهد. بنابراین فایل article.model.ts را به پوشه article اضافه کرده و یک کلاس تحت عنوان article در آن تعریف کنید. سپس کدهای زیر را اعمال کنید:

export class Article{
    title: string;
    link: string;
    votes: number;

    constructor(title: string, link: string, votes?: number){
        this.title = title;
        this.link = link;
        this.votes = votes || 0;
    }
}

در اینجا ما یک کلاس جدید تحت عنوان Article ایجاد کردیم. توجه داشته باشید که این یک کلاس خام است و کامپوننت انگولار نیست! در ساختار و الگوی معماری سه‌لایه، Model-View-Controller این کلاس یک Model می‌باشد.

هر مطلب یک title، یک link و یک مجموعه امتیاز دارد. هنگامیکه ما مطلب جدیدی را تولید می‌کنیم به title‌ و link نیاز داریم. پارامتر votes یک پارامتر دلخواه است که مقدار پیش‌فرض آن روی ۰ (صفر) تنظیم شده است (از علامت سوال انگلیسی ? برای دلخواه کردن یک فیلد استفاده می‌شود)

حال باید ArticleComponent را جهت استفاده از کلاس Article بروزرسانی کنیم. به جای ذخیره‌سازی مستقیم ویژگی‌ها در ArticleComponent، آنها را در یک نمونه از کلاس Article‌ ذخیره می‌کنیم. بنابراین فایل article.component.ts را به صورت زیر ویرایش می‌کنیم:

import { Component, OnInit } from '@angular/core';
import {Article} from "./article.model";

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
  article: Article;

  constructor() {
    this.article = new Article(
        'Roxo Online Tutorials',
        'http://www.roxo.ir',
        10
    );
  }

  voteUp(){
    this.article.votes += 1;
    return false;
  }

  voteDown(){
    this.article.votes -= 1;
    return false;
  }

  ngOnInit() {
  }

}

همانگونه که مشاهده کردید تمام ویژگی‌ها را به کلاس Article اضافه و سپس یک نوع article از کلاس Article تعریف کردیم. همچنین درون توابع voteUp و voteDown نیز تغییراتی را جهت ارتباط با کلاس article ایجاد کردیم. با این تغییر عناوینی که صورت گرفت طبیعتا باید view قالب ما نیز تغییراتی را داشته باشد. چون دیگر متغییری به نام votes وجود ندارد. بلکه تمام متغییرها باید به صورت article.votes تعریف شوند. بنابراین داریم:

<div class="row">
  <div class="col-md-3 text-center">
    <a href (click)="voteUp()"><i class="fa fa-arrow-up"></i></a>
    <a href (click)="voteDown()"><i class="fa fa-arrow-down"></i></a>
  </div>
  <div class="col-md-3 text-center"><a href="{{ article.link }}"> {{ article.title }} </a></div>
  <div class="col-md-3 text-center"><a href="{{ article.link }}"> {{ article.link }} </a></div>
  <div class="col-md-3 text-center"><span class="badge bg-red">{{ article.votes }}</span></div>
</div>

اگر صفحه مرورگر خود را بروز رسانی کنید متوجه خواهید شد که همه چیز به درستی کار می‌کند.

موضوعی که اینجا مطرح می‌شود عدم رعایت کردن بحث کپسوله کردن یا ایزوله کردن کدها برای متدهای voteUp و voteDown است زیرا ویژگی‌های این دو تابع به صورت مستقیم تغییر می‌کنند. برای حل این مشکل در ArticleComponent متدهای voteUp و voteDown را به کلاس Article انتقال می‌دهیم. بنابراین برای کلاس Article داریم:

export class Article{
    title: string;
    link: string;
    votes: number;

    constructor(title: string, link: string, votes?: number){
        this.title = title;
        this.link = link;
        this.votes = votes || 0;
    }

    voteUp(){
        this.votes += 1;
    }

    voteDown(){
        this.votes -= 1;
    }
    domain(){
        try{
            const link: string = this.link.split('//')[1];
            return link.split('/')[0];
        } catch (err){
            return null;
        }
    }
}

همچنین تغییرات زیر برای فراخوانی متدهای افزایش و کاهش امتیاز در کامپوننت ArticleComponent به صورت زیر می‌باشد:

import {Component, OnInit, Input} from '@angular/core';
import {Article} from "./article.model";

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
  article: Article;

  voteUp(): boolean{
    this.article.voteUp();
    return false;
  }

  voteDown(): boolean{
    this.article.voteDown();
    return false;
  }

  ngOnInit() {
  }

}

یک سوال: چرا متدهای voteUp و voteDown را هم در کامپوننت و هم در مدل تعریف کردیم؟
پاسخ: در هر دو کلاس ArticleComponent و Article متدهای voteUp() و voteDown() وجود دارد زیرا هر تابع مقدار کمی متفاوت عمل می‌کند. بنابراین تابع voteUp() در کامپوننت به component view ارتباط دارد، درحالیکه تایع voteUp() در مدل تغییرات اتفاق افتاده در model‌ را تعریف می‌کند. به عبارت دیگر توابع موجود در model یا کلاس Article تغییرات امتیازها را بررسی می‌کنند و اکثر درگیری‌ها در این بخش رخ می‌دهد و شما نمی‌خواهید برای هر درگیری مدام کامپوننت خود را فعال و غیرفعال کنید درحالیکه توابع موجود در کامپوننت‌ها تنها مقدار false را برای جلوگیری از refresh شدن صفحه استفاده می‌شوند و به‌گونه با view در ارتباط هستند.

اگر صفحه مرورگر خود را بروزرسانی کنید متوجه خواهید شد که همه چیز مرتب می‌باشد و تغییری در صفحه اصلی صورت نگرفته است.

ذخیره‌سازی چندین Article

حال نوبت آن رسیده است تا کدی برای در اختیار داشتن مجموعه‌ای از مطالب بنویسیم. کامپوننت AppComopnent را باز کرده و آن را با کدهای زیر بروزرسانی کنید:

import { Component } from '@angular/core';
import {Article} from "./article/article.model";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  host: {
    class: "row"
  }
})
export class AppComponent {
  articles: Article[];

  constructor(){
    this.articles = [
        new Article('Roxo Online Tutorials', 'http://www.roxo.ir', 3),
        new Article('Roxo Shop', 'http://shop.roxo.ir', 2),
        new Article('Roxo Forum', 'http://ask.roxo.ir', 2),
    ];
  }

  addArticle(title: HTMLInputElement, link: HTMLInputElement): boolean {
    console.log(`Adding article title: ${title.value} and link: ${link.value}`);
    this.articles.push(new Article(title.value, link.value, 0));
    title.value= '';
    link.value = '';
    return false;
  }
}

همینطور که در جریان هستید برای استفاده از کلاس Article باید همواره آن را ایمپورت کرد. بنابراین در خط دوم مجموعه کد بالا اینکار را انجام داده‌ایم.

شما با دستور جدید articles: Article[]‌ برخورد کرده‌اید. عبارت Article0[] یک مقدار ناآشنا به نظر می‌رسد. در واقع با این دستور اطلاع می‌دهید که articles به عنوان مجموعه‌ای از اشیاء Article می‌باشد. معمولا این دستور را به صورت Array<Article> نیز می‌نویسند. بنابراین، آرایه‌ها با دستور this.articles برای شما قابل دسترس خواهند بود.

تنظیم‌کردن ArticleComponent با input‌ها

با این تفاسیر هم اکنون ما مجموعه‌ای از Article مدل‌ها را داریم. اما سوال اینجاست که چگونه این مجموعه را به ArticleComponent ارسال کنیم؟

قبلا ما از Inputها استفاده کرده‌ایم. زمانی که دستور @Input فراخوانی می‌شود ما به ورودی‌های زیادی اشاره می‌کنیم. به عبارت دیگر به ازای هر ورودی یک سری عملیات را انجام می‌دهیم. همانگونه که قبلا مطرح کردیم با استفاده از [ ] می‌توان یک متغییر درون المان را به کامپوننت ارسال کنیم. بنابراین برای تگ <app-article> خواهیم داشت:

<app-article [article]="myArticle"></app-article>

بسیار عالی، و در نهایت فایل کامپوننت ما به صورت زیر خواهد بود:

import {Component, OnInit, Input} from '@angular/core';
import {Article} from "./article.model";

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
  @Input article: Article;

  voteUp(): boolean{
    this.article.voteUp();
    return false;
  }

  voteDown(): boolean{
    this.article.voteDown();
    return false;
  }

  ngOnInit() {
  }

}

رندر کردن لیستی از مطالب در قالب

همانگونه که ملاحظه کردید تنظیمات مربوط به AppComponent را جهت ذخیره کردن آرایه‌ها اعمال کردیم. هم اکنون این تنظیمات را برای نمایش و رندر کردن تمام مقالات گسترش می‌دهیم. برای انجام این‌کار به جای استفاده از تگ <app-article> این تگ را به همراه دستور NgFor جهت تکرار نمایش مطالب استفاده می‌کنیم. بنابراین در فایل app.component.html بعد از تگ Form تغییرات زیر را لحاظ خواهیم کرد:

<app-article
  *ngFor="let article of articles"
  [article]="article">
</app-article>

حال اگر صفحه مرورگر خود را بروزرسانی کنید با تصویر زیر مواجه می‌شوید:

سایت نظرسنجی مشابه reddit

مرتب‌سازی مطالب بر اساس امتیاز

در مراحل گذشته ما توانستیم یک مطلب را ذخیره کرده و در لیست خود به نمایش بگذاریم.  حال برای بهتر نمایش دادن آن می‌خواهیم یک تابع مرتب‌سازی بر اساس امتیاز به پروژه خود اضافه کنیم. بنابراین فایل app.component.ts‌ را باز کرده و کد زیر را به آن اضافه می‌کنیم:

sortArticles(): Article[] {
  return this.articles.sort((a: Article, b: Article) => b.votes - a.votes);
}

و سپس فایل مربوط به قالب app.component.html را نیز به صورت زیر ویرایش کنید:

<div class="row">
<!-- Horizontal Form -->
  <div class="col-md-8 col-center-block">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت لینک</h3>
      </div>
      <!-- /.box-header -->
      <!-- form start -->
      <form class="form-horizontal">
        <div class="box-body">
          <div class="form-group">
            <label for="title" class="col-sm-2 control-label">عنوان مطلب</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="title" placeholder="عنوان مطلب خود را وارد کنید" #newtitle>
            </div>
          </div>
          <div class="form-group">
            <label for="link" class="col-sm-2 control-label">لینک</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="link" placeholder="لینک مطلب را وارد کنید" #newlink>
            </div>
          </div>
        </div>
        <!-- /.box-body -->
        <div class="box-footer">
          <button type="submit" (click)="addArticle(newtitle, newlink)"  class="btn btn-info pull-right">ثبت</button>
        </div>
        <!-- /.box-footer -->
      </form>
    </div>

    <div class="box">
      <div class="box-header">
        <h3 class="box-title">نظرسنجی مطالب</h3>
      </div>
      <!-- /.box-header -->
      <div class="box-body no-padding">
        <div class="row">
            <div class="col-md-3 text-center">امتیازدهی</div>
            <div class="col-md-3 text-center">عنوان مطلب</div>
            <div class="col-md-3 text-center">لینک مطلب</div>
            <div class="col-md-3 text-center">مجموع امتیازها</div>
        </div>
          <app-article
            *ngFor="let article of sortArticles()"
            [article]="article">
          </app-article>
      </div>
      <!-- /.box-body -->
    </div>
    <!-- /.box -->

  </div>
  </div>
  <!-- /.box -->

به شما مجددا تبریک می‌گوییم. فصل ۱ از سری دوره آموزشی انگولار ۲ به زبان فارسی به اتمام رسید. هم اکنون شما نرم‌افزاری برای نظرسنجی کاربران نسبت به مطالب، ایجاد و کدنویسی کردید. سخت‌ترین مرحله‌ی هر کار شروع آن است. در فصل‌های بعدی به توضیحات تخصصی‌تری نسبت به انگولار ۲ میپردازیم.

برای افزایش تمرکز کاربران عزیز و جلوگیری از طولانی شدن مطالب، هر بخش را به قسمت‌های کوچکتری تبدیل کرده‌ایم. در لیست زیر تمام بخش‌ها و زیربخش‌های آموزشی مجموعه‌ی انگولار ۲ در اختیار شما قرار گرفته است.

توجه: دوستان عزیز آموزش ویدیویی انگولار ۵ از مقدماتی تا پیشرفته به زبان فارسی را می‌توانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)

آموزش حرفه ای انگولار ۵ به زبان فارسی


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید

دیدگاه‌های شما (3 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

صنم
18 تیر 1396
سلام؛ از آموزش خوبتون ممنونم، توی آموزش قید کردید که از فریم‌ورک CSS بوت استراپ استفاده کردید، میشه روش استفاده رو هم آموزش بدید؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

من
05 فروردین 1396
با سلام و خسته نباشید در زیر قسمت "رندر کردن لیستی از مطالب در قالب"، ngfor با f کوچک نوشته شده که باید با f بزرگ نوشته بشه (ngFor) البته توی قسمت مرتب سازی درست آورده شده ولی توی اون قسمت مشکل داره با تشکر فراوان

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
05 فروردین 1396
با سلام و ضمن تبریک سال نو اصلاحات صورت گرفت. با تشکر

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

نام *
30 اسفند 1395
سلام ضمن تشکر فراوان و خسته نباشی در قسمت "ایجاد قالب ArticleComponent" قبل از اضافه کردن مدل از article.link و article.title استفاده شده در حالی که بایستی از link و title به تنهایی استفاده میشد

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
01 فروردین 1396
سلام وقت شما بخیر سال نو رو به شما و تمام هموطنان گرامی تبریک عرض می‌کنیم، عبارتهایی که ذکر کردید کاملا صحیح استفاده شده است و ایرادی در مثال نیست. زیرا article به عنوان یک کلاس ماژول است و بر اساس مبانی شیء گرایی برای دسترسی به مقادیر موجود در title باید از article.title و برای دستیابی به مقادیر link‌ باید از عبارت article.title‌ استفاده کنیم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

نام *
01 فروردین 1396
سلام با تشکر از زحمات شما و تبریک سال جدید و آرزوی بهترین ها برای شما ۱- منظور من استفاده از article.title قبل از اضافه کردن article.modle.ts بود.یا حدقل به من ایندخطا رو میداد که با حذف article مشکل بر طرف شد ۲- بعد از اضافه کردن مدل و تغییرات نهایی با خطای زیر روبرو میشم.لطفا راهنمایی کنید : Unhandled Promise rejection: Template parse errors: Can't bind to 'article' since it isn't a known property of 'app-article'. 1. If 'app-article' is an Angular component and it has 'article' input, then verify that it is part of this module. 2. If 'app-article' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. (" ][article]="article"> "): AppComponent@48:12 ; Zone: ; Task: Promise.then ; Value:

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
02 فروردین 1396
در صورتیکه همچین خطایی دارید باید بررسی کنید که آیا داخل کلاس کامپوننت ویژگی article را تعریف کرده اید یا خیر؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.