Как применить стили к элементу div, щелкнув его дочерние элементы (angular2 / ts)

HTML

<div class = "tableRow">
  <div id = "0-0">
    <p>Point {{levelOne}}</p>
  </div>
  <div id = "0-1" (click) = "select($event)">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod  </li>
  </div>
  <div id = "0-2" (click) = "select($event)">
    <li >Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod. </li>
  </div>
  <div id = "0-3" (click) = "select($event)">
    <li>
      Lorem ipsum dolor sit amet, 
    </li>
  </div>
  <div id = "0-4" (click) = "select($event)">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
        <li>lorem ipsum dolor</li>
  </div>
  <div id = "0-5" (click) = "select($event)">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
  </div>
</div>

CSS

.tableRow {
  width: 90%;
  display: grid;
  grid-template-columns: 10% 18% 18% 18% 18% 18%;
}

.tableRow > div {
  background: $white;
  padding: 1em;
  border: 1px solid $purple-70;
  text-align: center;
  cursor: pointer;
}

.tableRow > div:first-child {
  font-weight: bold;
  background: $purple-10;
  cursor: default;
}

.selected {
  background-color: red !important;
}

TS

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

    @Component({
      selector: "example",
      templateUrl: "./example.component.html"
    })
    export class Example implements OnInit {

      public levelOne: Number = 1;
      public levelTwo: Number = 3;
      public levelThree: Number = 9;
      public LevelFour: Number = 27;

      public selected = false;

      constructor() {}

      ngOnInit() {}


    select($event) {
      let id = $event.target.id;
      if ($event.target.localName !== "div") {
        let id = $event.target.parentElement.id;
      }
    console.info(id);
   }

  }

со следующим кодом, щелчок за пределами элемента li приводит к тому, что id устанавливается на фактический идентификатор, но когда я нажимаю на элемент li внутри идентификатора div, устанавливается значение undefined ... однако, если я регистрирую $ event.target.parentElement.id на консоли, он напечатает правильный ID при нажатии на элемент li.

Я почти уверен, что если я смогу получить правильный идентификатор, захваченный при щелчке, я могу использовать его для назначения стиля (например, изменить цвет фона div)

Я не уверен, что делаю не так, или вообще есть способ лучше?

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
0
0
279
2

Ответы 2

Обычно это плохая практика (по слишком многим причинам, чтобы перечислять здесь) напрямую обращаться к dom при использовании angular. С помощью инструментов, предоставляемых Angular, вы можете делать практически все, что угодно, например:

<div [class.selected] = "div1Selected" (click) = "div1Selected = !div1Selected">
    Has class `selected` when component's property `div1Selected` is true.
</div> 

Является ли просто чтение идентификатора цели MouseEvent «прямым доступом к DOM»? Angular и TypeScript изначально поддерживают объекты MouseEvent. Вы даже можете присвоить им соответствующий тип. выберите ($ event: MouseEvent), а затем Intellisense TypeScript покажет вам, какие именно свойства / методы доступны для этого события.

diopside 01.05.2018 20:44

Да. Это не "угловой способ" зависеть от идентификаторов элементов ... Делая это, вы упускаете большую часть реальной силы Angular, и было бы лучше узнать, как добиться чего-то, не прибегая к этому.

funkizer 01.05.2018 20:54

Я обычно понимаю причины, по которым не читаются собственные свойства DOM, но в какой альтернативной среде было бы проблематично читать идентификаторы? Не могли бы вы просто проверить, является ли цель HTMLElement и есть ли у нее идентификатор, и если да, то использовать его? Если нет, прибегнуть к другому методу таргетинга? Мне искренне любопытно, т.к. я иногда использую этот метод в своем собственном коде в качестве альтернативы созданию потенциально тысяч отдельных прослушивателей событий или отдельных компонентов внутри циклов ngFor. Я программно привязываю идентификатор к чему-то уникальному с помощью id = "{{any}}", а затем выбираю w, что

diopside 01.05.2018 20:57

В цикле * ngFor вы можете просто передать текущий элемент функции, например. * ngFor = "let item of items" (click) = "clicked (item)"

funkizer 01.05.2018 21:02

и предположим, что вы хотите изменить стиль элемента, по которому щелкнули мышью, просто переключите какой-либо флаг в элементе, например. item.selected =! item.selected, а затем вы можете привязать его к классу стиля

funkizer 01.05.2018 21:04

Но тогда это создает отдельный прослушиватель событий для каждого элемента, сгенерированного циклом for, верно? Вот чего я пытался избежать. Это становится проблематичным, если я, скажем, использую цикл for для создания тысяч строк в электронной таблице. Я всегда предполагал, что одноразовая привязка идентификатора более производительна, чем отдельные, постоянно включенные слушатели.

diopside 01.05.2018 21:04

Да, но это не особо важно. У вас могут быть десятки тысяч элементов с привязкой (щелчком), прежде чем это станет напряжением. И рендеринг dom, вероятно, сам по себе является большим стрессом. В таком случае в любом случае потребуется разбивка на страницы или виртуальная прокрутка.

funkizer 01.05.2018 21:09

Но да, на мой взгляд, в некоторых случаях вполне нормально использовать общий прослушиватель кликов для всей таблицы, например, если вам не нужна разбивка на страницы :)

funkizer 01.05.2018 21:11

проверьте эту потрясающую виртуальную библиотеку прокрутки, кстати. Действительно эффективен, когда вы визуализируете только те элементы, которые соответствуют области просмотра и повторно используете элементы :) github.com/aminpaks/angular-virtual-list

funkizer 01.05.2018 21:13

Интересно ... Я думаю, мне нужно провести несколько тестов между привязкой тысяч идентификаторов и созданием тысяч слушателей. Я всегда предполагал, что один из них намного эффективнее другого, но, честно говоря, никогда не тестировал его. Это действительно единственный вариант использования, в котором я полагаюсь на идентификаторы. если это не имеет большого значения, я проведу рефакторинг своего кода! Спасибо за совет

diopside 01.05.2018 21:14

Я бы просто использовал привязку стиля, чтобы привязать любой стиль, который вы хотите, к родительскому div, а затем использовать щелчки дочернего div, чтобы изменить значение строки, привязанной к этому стилю.

<div class = "tableRow" [style.background] = "myStyle">
  <div id = "0-0">
    <p>Point {{levelOne}}</p>
  </div>
  <div id = "0-1" (click) = "myStyle = 'red'">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod  </li>
  </div>
  <div id = "0-2" (click) = "myStyle = 'blue'">
    <li >Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod. </li>
  </div>
  <div id = "0-3" (click) = "myStyle = 'green'">
    <li>
      Lorem ipsum dolor sit amet, 
    </li>
  </div>
  <div id = "0-4" (click) = "myStyle = 'orange'">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
        <li>lorem ipsum dolor</li>
  </div>
  <div id = "0-5" (click) = "myStyle = 'magenta'">
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
  </div>
</div>

Составная часть

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

@Component({
  selector: "example",
  templateUrl: "./example.component.html"
})
export class Example implements OnInit {

  public levelOne: Number = 1;
  public levelTwo: Number = 3;
  public levelThree: Number = 9;
  public LevelFour: Number = 27;

  myStyle = 'inherit';

  public selected = false;

  constructor() {}

  ngOnInit() {}

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

  <div class = "tableRow" [style.background] = "myStyle" (click) = "setStyle($event)">

Затем просто добавьте в свой компонент функцию, аналогичную той, что у вас уже есть.

select($event) {
  let id = ($event.target as HTMLElement).id;
  // here you could add a a switch case that sets the myStyle string based on the id of the clicked element

Другие вопросы по теме