Как скрыть и показать текст при нажатии после определенной длины в Angular10?

#javascript #angular

#javascript #angular

Вопрос:

У меня длинный текст. Я пытаюсь добавить кнопки «Показать больше» и «Показать меньше», чтобы показать и скрыть текст после определенной длины с анимацией. Я знаю, как отображать и скрывать определенный текст по щелчку. Но это выглядит не очень хорошо. Я также пробовал с CSS: overflow property. Но он просто скрывает текст.

Я хочу скрыть текст в html после 15 символов и отобразить кнопку. Когда я нажимаю на кнопку, она должна расшириться и показать мне оставшееся, а содержимое кнопки должно быть изменено на «Показывать меньше»

 function func(){
    alert("hi");
} 
 a {
    color: blue;
    text-decoration: underline;
    cursor: pointer;
} 
 <div class="more">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Vestibulum laoreet, nunc eget laoreet sagittis,
    quam ligula sodales orci, congue imperdiet eros tortor ac lectus.
    Duis eget nisl orci. Aliquam mattis purus non mauris
    blandit id luctus felis convallis.
    Integer varius egestas vestibulum.
    Nullam a dolor arcu, ac tempor elit. Donec.
</div>

<a onClick="func()">Show more</a> 

Комментарии:

1. Я думаю, вам нужно предоставить более подробную информацию о вашей проблеме. Вы ищете общее назначение или решение, специфичное для вашей структуры.

2. Я хочу, чтобы при нажатии на кнопку скрывался и отображался текст длиной после 15 символов.

Ответ №1:

Я думаю, что могу предложить часть решения. Вот Стекблитц

Единственная проблема заключается в том, что свойства css overflow и text-overflow не могут быть анимированы, поэтому у вас не будет плавного перехода… Для этого вы можете либо создать определенную анимацию, либо использовать другой подход css, например, изменить высоту или использовать непрозрачность и задержку перехода. Также для проверки длины содержимого вам потребуется больше логики, которую я не включил в это решение, поскольку я не думаю, что это было бы необходимо, потому что вы могли бы ограничить ширину элемента и, следовательно, вырезать текст.

Ответ №2:

Вставьте компонент Hide / Reveal ‘Panel’ с помощью директивы

В этом подходе мы применяем стратегию присоединения директивы к произвольному элементу уровня блока, содержащему один TextNode в качестве прямого потомка, с целью упаковки этого TextNode в компонент, который может обрезать его длину с помощью функций раскрытия / скрытия.

Решение потребует

  • 1 Директива
  • 1 Компонент

Почему такой подход

  • Мы не хотим беспокоиться о состоянии логики hide / show в каждом компоненте, который должен реализовать это поведение, поэтому будет лучше, если мы сможем разбить его на компоненты и заставить его работать непосредственно со своим собственным состоянием
  • Мы хотим иметь возможность легко изменять внешний вид функции «Показать / скрыть» во всех режимах использования.
  • мы можем применить любую необходимую анимацию с помощью состояний Angular Animations в самом компоненте.

Компонент

Сначала мы создадим наш компонент, потому что от него зависит наша директива, чтобы иметь возможность его создать.

контроллер

 export class TruncateWrapperComponent implements OnInit {
  private _longText!: string
  private _shortText!: string;
  showLess = true;

  constructor(private change: ChangeDetectorRef) {
  }

  ngOnInit(): void {
  }

  setTruncateContent(truncateLength: number, textNode: Node) {
    this._longText = textNode.textContent ?? "";
    this._shortText = this._longText.slice(0, truncateLength);
    this.change.detectChanges();
  }

  get short() {
    return this._shortText
  }

  get long() {
    return this._longText;
  }
  
}
 

обратите внимание: мы должны импортировать ChangeDetectorRef, потому что мы будем устанавливать частные свойства longText и ShortText непосредственно из нашей директивы вне цикла Angular changeDetection.

Шаблон

 <div>
  <ng-container *ngIf="showLess; else more">
    <div>
      {{short}}
    </div>
    <div>
      <button (click)="showLess = !showLess">Show more</button>
    </div>
  </ng-container>


  <ng-template #more>
      <div>
        {{long}}
      </div>
      <div>
        <button (click)="showLess = !showLess">Show Less</button>
      </div>
  </ng-template>
</div>
 

Директива

Теперь, когда у нас есть компонент, давайте создадим директиву, которую мы можем использовать в других наших шаблонах для вставки компонента.

 @Directive({selector: '[truncate]'})
export class TruncateDirective implements AfterContentInit {
  @Input() truncate: number = 15;
  textNode!: Node;
  private readonly componentFactory: ComponentFactory<TruncateWrapperComponent>;

  constructor(private element: ElementRef<HTMLElement>,
              private render: Renderer2,
              private viewContainer: ViewContainerRef,
              factoryResolver: ComponentFactoryResolver) {
    // prime a component factory for creating the wrapper component.
    this.componentFactory = factoryResolver.resolveComponentFactory(TruncateWrapperComponent)
  }

  ngAfterContentInit() {
    if (this.shouldProcess()) {
      this.createWrapper();
    }
  }

  /**
   * shouldProcess checks the nativeElement which the directive is attached to for any direct descendent textNodes. The
   * first textNode encountered will be inserted into the TruncateWrapperComponent. Any original content other than
   * the first textNode encountered will be removed when the wrapper is created.
   *
   * If no direct textNode descendants are found no wrapper will be created and the original content will remain.
   */
  shouldProcess() {
    // check for textNodes, which is nodeType 3.
    const children = this.element.nativeElement.childNodes;
    for (let i = 0; i < children.length; i  ) {
      if (children[i].nodeType == 3) {
        this.textNode = children[i];
        break;
      }
    }
    return Boolean(this.textNode);
  }

  createWrapper() {
    // clear current content
    this.render.setProperty(this.element.nativeElement, 'innerHTML', '');
    // attach new component to view.
    const wrapText = this.viewContainer.createComponent(this.componentFactory);
    wrapText.instance.setTruncateContent(this.truncate, this.textNode);
  }
}
 

StackBlitz

Вот StackBlitz, демонстрирующий реализацию