কৌনিক 2 এ <ng- কনটেন্ট> খালি কিনা তা যাচাই করবেন কীভাবে?


92

ধরুন আমার একটি উপাদান রয়েছে:

@Component({
    selector: 'MyContainer',
    template: `
    <div class="container">
        <!-- some html skipped -->
        <ng-content></ng-content>
        <span *ngIf="????">Display this if ng-content is empty!</span>
        <!-- some html skipped -->
    </div>`
})
export class MyContainer {
}

এখন, আমি <ng-content>এই উপাদানটির জন্য খালি থাকলে কিছু ডিফল্ট সামগ্রী প্রদর্শন করতে চাই । ডমকে সরাসরি অ্যাক্সেস না করে এটি করার কী সহজ উপায় আছে?



এফওয়াইআই, আমি স্বীকৃত উত্তরটি কাজ করে জানি, তবে আমি মনে করি যে "ইউজডেফল্ট" টাইপের ইনপুট প্যারামিটারগুলিকে মিথ্যাতে ডিফল্ট করে দেওয়া ভাল স্টাইল।
bryan60

উত্তর:


97

এর ng-contentমতো কোনও divস্থানীয় রেফারেন্স পেতে কোনও এইচটিএমএল উপাদানটিকে মোড়ক করুন, তারপরে এই ngIfঅভিব্যক্তিটি আবদ্ধ করুন ref.children.length == 0:

template: `<div #ref><ng-content></ng-content></div> 
           <span *ngIf="ref.nativeElement.childNodes.length == 0">
              Display this if ng-content is empty!
           </span>`

24
এর কোন বিকল্প উপায় নেই? কারণ এটি অরিলিয়া, অরেলিয়া ফ্যালব্যাক স্লটের তুলনায়
নভোচারী

18
এটি ব্যবহার করা নিরাপদ ref.children.length। চাইল্ডনোডগুলিতে textনোডগুলি থাকবে যদি আপনি স্থান বা নতুন লাইনের সাথে আপনার এইচটিএমএল ফর্ম্যাট করেন তবে শিশুরা এখনও খালি থাকবে।
সংসদ

4
অ্যাংুলার ইস্যু ট্র্যাকারটিতে আরও ভাল পদ্ধতির জন্য একটি বৈশিষ্ট্য অনুরোধ রয়েছে: github.com/angular/angular/issues/12530 (সেখানে +1 যোগ করার উপযুক্ত হতে পারে)।
এপসিলন

4
আমি পোস্ট করতে যাচ্ছিলাম যে আমি এটির ref.childNodes.length == 0বদলে উদাহরণটি ব্যবহার না করা অবধি এই কাজ করছে বলে মনে হচ্ছে না ref.children.length == 0। আপনি যদি সামঞ্জস্যপূর্ণ উত্তরটি সম্পাদনা করতে পারেন তবে এটি একগুচ্ছকে সহায়তা করবে। সহজ ভুল, আপনাকে ধর্ষণ করা নয়। :)
ডাস্টিন ক্লেভল্যান্ড

4
আমি এই উদাহরণটি অনুসরণ করেছি এবং এটি আমার পক্ষে ভাল কাজ করে। তবে আমি !ref.hasChildNodes()তার পরিবর্তে ব্যবহার করেছিref.nativeElement.childNodes.length == 0
সের্গে ডিজুবা

34

@ পিক্সেলবিটের উত্তরে কিছু অনুপস্থিত। আমাদের কেবল childrenসম্পত্তিটিই পরীক্ষা করা দরকার , কারণ প্যারেন্ট টেমপ্লেটে যে কোনও লাইন ব্রেক বা স্পেস childrenফাঁকা পাঠ্য \ লাইন ব্রেকগুলির সাথে উপাদান তৈরি করে। চেক করা ভাল .innerHTMLএবং .trim()এটি।

কাজের উদাহরণ:

<span #ref><ng-content></ng-content></span>
<span *ngIf="!ref.innerHTML.trim()">
    Content if empty
</span>

4
আমার জন্য সেরা উত্তর :)
কামিল কিয়েসজেউস্কি

সন্তানের উপাদানটি খালি কিনা তা যাচাই করার জন্য কি আমরা এই পদ্ধতিটি ব্যবহার করতে পারি এবং যদি তা হয় তবে অভিভাবকদের আড়াল করতে পারি? আমি চেষ্টা করেছি, ভাগ্য নেই
কাবিন্দ জয়কোডি

কভিন্দজায়াকোডি হ্যাঁ, এটি খালি জন্য শিশু উপাদান পরীক্ষা করবে। আপনার কোডটি দেখান।
lfoma

* ngIf = "! ref.innerHTML.trim ()" এই অংশটি পারফরম্যান্সের সমস্যার কারণ হবে। ছাঁটাই হ'ল ও (এন)।
র্যান্ডমকোড

4
@ র্যান্ডমকোড ঠিক আছে, ফাংশনটি একাধিকবার ডাকা হবে। একটি ভাল উপায় যা আপনি জিজ্ঞাসা করতে চান তার উপর নির্ভর করে চেক করা element.children.length বা element.childnodes.length
স্টিফান রিন

32

সম্পাদনা 17.03.2020

খাঁটি সিএসএস (২ টি সমাধান)

কোনও কিছুই এনজি-কনটেন্টে প্রজেক্ট না করা থাকলে ডিফল্ট সামগ্রী সরবরাহ করে।

সম্ভাব্য নির্বাচক:

  1. :only-childনির্বাচক। এখানে এই পোস্টটি দেখুন :: একমাত্র শিশু নির্বাচক

    এটির জন্য কম কোড / মার্কআপ প্রয়োজন। আইই 9 এর পরে থেকে সমর্থন: আমি কি ব্যবহার করতে পারি: কেবলমাত্র শিশু

  2. :emptyনির্বাচক শুধু আরও পড়ুন।

    আইই 9 এবং আংশিক আই 7/8 থেকে সমর্থন: https://caniuse.com/#feat=css-sel3

এইচটিএমএল

<div class="wrapper">
    <ng-content select="my-component"></ng-content>
</div>
<div class="default">
    This shows something default.
</div>

সিএসএস

.wrapper:not(:empty) + .default {
    display: none;
}

যদি এটি কাজ করে না

সচেতন থাকুন, কমপক্ষে একটি সাদা জায়গা থাকা খালি মৌমাছি না বলে বিবেচিত হয়। কৌণিক সাদা স্থান সরিয়ে দেয়, তবে কেবল যদি তা না হয়:

<div class="wrapper"><!--
    --><ng-content select="my-component"></ng-content><!--
--></div>

বা

<div class="wrapper"><ng-content select="my-component"></ng-content</div>

4
এখনও পর্যন্ত এটি আমার ব্যবহারের ক্ষেত্রে সবচেয়ে ভাল সমাধান ছিল। আমি মনে করছিলাম না যে আমাদের একটি emptyসিএসএস সিউডোক্লাস ছিল
জুলিয়ানোব্র্যাসিল

@ স্টেফান ডিফল্ট সামগ্রী যেভাবেই রেন্ডার করা হবে ... এটি কেবল লুকানো থাকবে। সুতরাং, জটিল ডিফল্ট সামগ্রীর জন্য এটি সেরা সমাধান নয়। এটা কী ঠিক?
BossOz

4
@ বসোজ আপনি ঠিক বলেছেন এটি রেন্ডার করা হবে (কনস্ট্রাক্টর ইত্যাদি ডাকা হবে যদি আপনার একটি কৌণিক উপাদান থাকে)। এই সমাধানটি বোবা দর্শনের জন্য কেবল ভাল কাজ করে। আপনার যদি জটিল যুক্তি থাকে, তার মধ্যে লোডিং বা এমন জিনিস জড়িত থাকে তবে আমার মতে আপনার সেরা বাজিটি একটি কাঠামোগত দিকনির্দেশনা লিখতে হবে, যা কোনও টেম্পলেট / শ্রেণি পেতে পারে (তবে আপনি এটি প্রয়োগ করতে চান) এবং যুক্তির উপর নির্ভর করে, তারপর রেন্ডার করুন পছন্দসই উপাদান বা ডিফল্ট এক। মন্তব্যের বিভাগটি উদাহরণের জন্য খুব ছোট। আমরা আমাদের অ্যাপ্লিকেশনগুলির একটিতে থাকা অন্য একটি উদাহরণের জন্য আবার মন্তব্য করি।
স্টেফান রেইন

একটি উপায়ে কনটেন্টচিল্ড্রেনকে একটি নির্দেশিকা (ডাইরেক্টিভ ক্লাসের সাথে জিজ্ঞাসা, তবে কাঠামোগত দিকনির্দেশক হিসাবে ব্যবহার, সুতরাং কেবল চিহ্নিতকরণের সাথে জড়িত কোনও প্রাথমিক বুটস্ট্র্যাপিং নেই) হতে পারে: <loader [data]="allDataWeNeed"> <desired-component *loadingRender><desired-component> <other-default-component *renderWhenEmptyResult></other-default-component> </loader>এবং লোডিং উপাদানটিতে আপনি পারফরম্যান্স লোডিং বোঝাতে পারবেন, যখন ডেটা লোড হচ্ছে। আপনি বিভিন্নভাবে এটি লিখতে / সমাধান করতে পারেন। এটি কীভাবে আপনি এটি সমাধান করতে পারেন তা এটি একটি প্রদর্শন।
স্টিফান রেইন

21

আপনি যখন সামগ্রীটি ইনজেক্ট করবেন তখন একটি রেফারেন্স ভেরিয়েবল যুক্ত করুন:

<div #content>Some Content</div>

এবং আপনার উপাদান শ্রেণিতে @ কনটেন্টচিল্ড () এর সাথে ইনজেকশনযুক্ত সামগ্রীর একটি রেফারেন্স পান

@ContentChild('content') content: ElementRef;

সুতরাং আপনার উপাদান টেমপ্লেটে আপনি সামগ্রী ভেরিয়েবলের কোনও মান আছে কিনা তা পরীক্ষা করতে পারেন

<div>
  <ng-content></ng-content>
  <span *ngIf="!content">
    Display this if ng-content is empty!
  </span>    
</div> 

এটি সবচেয়ে পরিষ্কার এবং আরও ভাল উত্তর। এটি বাক্সের বাইরে থাকা সামগ্রী চাইল্ড এপিআই সমর্থন করে। শীর্ষ উত্তর কেন এত বেশি ভোট পেয়েছিল তা বুঝতে পারি না।
কার্বনড্রি

10
ওপি এনজি কনটেন্ট খালি কিনা তা জানতে চেয়েছিল - এর অর্থ <MyContainer></MyContainer>। আপনার সমাধান ব্যবহারকারীদের একটি উপ-উপাদান MyContainer অধীনে তৈরি করতে প্রত্যাশা করে: <MyContainer><div #content></div></MyContainer>। যদিও এটি একটি সম্ভাবনা, আমি এটি উচ্চতর বলব না।
পিক্সিটসেট

8

ইনজেকশন দিন elementRef: ElementRefএবং elementRef.nativeElementকোনও সন্তান আছে কিনা তা পরীক্ষা করুন । এটি শুধুমাত্র সাথে কাজ করতে পারে encapsulation: ViewEncapsulation.Native

<ng-content>ট্যাগটি মোড়ানো এবং এটির কোন সন্তান আছে কিনা তা পরীক্ষা করে দেখুন। এটি দিয়ে কাজ করে না encapsulation: ViewEncapsulation.Native

<div #contentWrapper>
  <ng-content></ng-content>
</div>

এবং এটির কোন সন্তান আছে কিনা তা পরীক্ষা করে দেখুন

@ViewChild('contentWrapper') contentWrapper;

ngAfterViewInit() {
  contentWrapper.nativeElement.childNodes...
}

(পরীক্ষিত না)


4
আমি ব্যবহারের কারণে এটিকে হ্রাস করেছিলাম @ViewChild। "আইনী" থাকাকালীন ভিউচিল্ড কোনও টেমপ্লেটের মধ্যে চাইল্ড-নোডগুলি অ্যাক্সেসের জন্য ব্যবহার করা উচিত নয়। এটি একটি অ্যান্টিপ্যাটার্ন কারণ, যদিও বাবা-মা শিশুদের সম্পর্কে জানতে পারেন তবে তাদের সাথে তাদের দম্পতি হওয়া উচিত নয় কারণ এটি সাধারণত প্যাথলজিকাল কাপলিংয়ের দিকে নিয়ে যায় ; ডেটা-ট্রান্সপোর্ট বা অনুরোধ-হ্যান্ডলিংয়ের আরও উপযুক্ত ফর্ম হ'ল ইভেন্ট-চালিত পদ্ধতিগুলি ব্যবহার করা
কোডি

4
@ কোডটি আপনার ডাউনটাতে একটি মন্তব্য পোস্ট করার জন্য ধন্যবাদ আসলে আমি আপনার যুক্তি অনুসরণ করি না। টেমপ্লেট এবং উপাদান শ্রেণি একটি একক - একটি উপাদান। কোড থেকে টেমপ্লেট অ্যাক্সেস করা একটি প্রতিরোধী হওয়া উচিত তা আমি দেখতে পাচ্ছি না। উভয় ওয়েব ফ্রেমওয়ার্ক এবং নাম ব্যতীত কৌণিক (2/4) কৌণিকের সাথে প্রায় কিছুই মিল নেই almost
গন্টার জ্যাচবাউয়ার

4
গন্টার, আপনি দুটি সত্যিই ভাল পয়েন্ট করা। কৌণিকর অগত্যা অ্যাঙ্গুলারজেএস এর উপায়ে কলঙ্কযুক্ত হওয়া উচিত নয়। তবে আমি চিহ্নিত করব যে প্রথম পয়েন্টটি (এবং আমি উপরে তৈরি করেছি) প্রকৌশল দার্শনিক গিটার দিকে পড়ে toward এটি বলেছিল, আমি সফটওয়্যার কাপলিংয়ের বিশেষজ্ঞের মধ্যে পরিণত হয়েছি এবং আমি [কমপক্ষে ভারী] ব্যবহারের বিরুদ্ধে পরামর্শ দেব @ViewChild। আমার মন্তব্যে কিছুটা ভারসাম্য যুক্ত করার জন্য ধন্যবাদ - আমি আমাদের উভয় মন্তব্যকে অন্যের মতো বিবেচনার জন্য উপযুক্ত বলে মনে করি।
কোডি

4
@ কোডি আপনার পক্ষে সম্ভবত @ViewChild()এই নামটি থেকেই আসে। "বাচ্চারা" অগত্যা বাচ্চাদের নয়, তারা কেবলমাত্র উপাদানটির ঘোষণামূলক অংশ (যেমনটি আমি দেখছি)। যদি এই মার্কআপের জন্য তৈরি উপাদানগুলির উদাহরণগুলি অ্যাক্সেস হয় তবে এটি অবশ্যই আলাদা গল্প story এটি একটি খুব আকর্ষণীয় আলোচনা। এটি আমাকে চিন্তিত করে যে এই ধরণের বিষয়ে চিন্তা করার মতো পর্যাপ্ত সময় আমার কাছে নেই কারণ এই জাতীয় ফ্রেমওয়ার্কগুলির সাথে খুব বেশি সময় কোনও উপায় খুঁজে পাওয়ার জন্য খুব বেশি সময় নষ্ট হয়।
গন্টার জ্যাচবাউয়ার


5

আপনি যদি কোনও ডিফল্ট সামগ্রী প্রদর্শন করতে চান তবে আপনি কেবল CSS থেকে 'একমাত্র-সন্তানের' নির্বাচককে কেন ব্যবহার করবেন না।

https://www.w3schools.com/cssref/sel_only-child.asp

যেমন: এইচটিএমএল

<div>
  <ng-content></ng-content>
  <div class="default-content">I am deafult</div>
</div>

সিএসএস

.default-content:not(:only-child) {
   display: none;
}

বরং স্মার্ট সমাধান, যদি আপনি ভিউচিল্ড এবং উপাদানগুলিতে স্টাফগুলি মোকাবেলা করতে না চান। আমি এটা পছন্দ করি!
এমসিয়ের তোফ '

অনুগ্রহ করে লক্ষ্য করুন যে
প্রতিলিপি

2

কৌণিক 10 এর সাথে এটি কিছুটা পরিবর্তিত হয়েছে। আপনি ব্যবহার করবেন:

<div #ref><ng-content></ng-content></div> 
<span *ngIf="ref.children.length == 0">
  Display this if ng-content is empty!
</span>

1

আমার ক্ষেত্রে আমাকে খালি এনজি-কন্টেন্টের পিতামাতাকে আড়াল করতে হবে:

<span class="ml-1 wrapper">
  <ng-content>
  </ng-content>
</span>

সাধারণ সিএসএস কাজ করে:

.wrapper {
  display: inline-block;

  &:empty {
    display: none;
  }
}

1

আমি @ কনটেন্টচিল্ডেন ডেকরেটার ব্যবহার করে একটি সমাধান কার্যকর করেছি , এটি @ লার্নারের উত্তরের মতোই।

ডক্স অনুসারে , এই সাজসজ্জা:

DOM বিষয়বস্তু থেকে উপাদান বা নির্দেশের কোয়েরি তালিকা পান। যে কোনও সময় কোনও শিশু উপাদান যুক্ত করা, অপসারণ বা সরানো হলে ক্যোয়ারী তালিকা আপডেট করা হবে এবং কোয়েরি তালিকার পর্যবেক্ষণযোগ্য পরিবর্তনগুলি একটি নতুন মান নির্গত করবে।

সুতরাং প্যারেন্ট উপাদানগুলির প্রয়োজনীয় কোডটি হ'ল:

<app-my-component>
  <div #myComponentContent>
    This is my component content
  </div>
</app-my-component>

উপাদান শ্রেণিতে:

@ContentChildren('myComponentContent') content: QueryList<ElementRef>;

তারপরে, উপাদান টেমপ্লেটে:

<div class="container">
  <ng-content></ng-content>
  <span *ngIf="*ngIf="!content.length""><em>Display this if ng-content is empty!</em></span>
</div>

পুরো উদাহরণ : https://stackblitz.com/edit/angular-jjjdqb

আমি এই সমাধান, কৌণিক উপাদান বাস্তবায়িত জন্য পেয়েছি matSuffix, এ ফর্ম-ক্ষেত্র অংশটি।

পরে যখন উপাদানটির বিষয়বস্তু ইনজেক্ট করা হয়, অ্যাপটি শুরু করার পরে , আমরা এছাড়াও এর changesইভেন্টটির সাবস্ক্রাইব করে একটি প্রতিক্রিয়াশীল প্রয়োগ করতে পারি QueryList:

export class MyComponentComponent implements AfterContentInit, OnDestroy {
  private _subscription: Subscription;
  public hasContent: boolean;

  @ContentChildren('myComponentContent') content: QueryList<ElementRef>;

  constructor() {}

  ngAfterContentInit(): void {
    this.hasContent = (this.content.length > 0);
    this._subscription = this.content.changes.subscribe(() => {
      // do something when content updates
      //
      this.hasContent = (this.content.length > 0);
    });
  }

  ngOnDestroy() {
    this._subscription.unsubscribe();
  }

}

সম্পূর্ণ উদাহরণ : https://stackblitz.com/edit/angular-essvnq

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.