Home > Mobile >  Detect the next line in flex box containing div
Detect the next line in flex box containing div

Time:02-12

I need to add the vertical line splitter between the div. But the div which is present at the end of the line should not contain the splitter. The div will be placed dynamically.

https://stackblitz.com/edit/angular-ivy-lxhcuu?file=src/app/app.component.css

document.addEventListener('DOMContentLoaded', () => {
  const parent = document.querySelector(".parent");
  const node = parent.firstElementChild;
  for (let i = 1; i < 30; i  ) {
    parent.appendChild(node.cloneNode(true));
  }
});
p {
  font-family: Lato;
}

.parent {
  display: flex;
  flex-flow: wrap;
}

.paddingDta {
  padding: 5px;
}

.divider {
  border-left: 1px solid red;
}

.dividerPadding {
  margin: 2px;
}
<div >
  <div>
    <div >
      {{ data }}
      <span ></span>
    </div>
  </div>
</div>

on small screen

on large screen

CodePudding user response:

Well... This is kinda sophisticated problem, that can be solved in many different ways depending on usecase.

But long story short, I don't know any "tricky" way to fix this issue without "bruteforcing" it with checking position of every element on the list:

// I've used custom directive for this example for easier hook
// But you can use local variables as well 
<div  [someName]="i"> <-- content --> </div>

// View Children to hook to HTMLElement of our list items
@ViewChildren(FlexBorderDirective) els: QueryList<FlexBorderDirective>;

Then you need to check offset position of every element and check which is further from left side of the screen. I've used function like this, however you might think about better way to check each element:

checkLastElements(_elements: Array<HTMLDivElement>) {
  // Clear table for resize
  this.lastElementsIndexes = [];

  // Not optimal, but good enough for example
  for (let i = 0; i < _elements.length; i  ) {
    if (i   1 < _elements.length)
      if (_elements[i].offsetLeft > _elements[i   1].offsetLeft) {
        // Push "last element index" to another array for checking
        this.lastElementsIndexes.push(i);
      }
  }

  // "Force push" last element to our list
  this.lastElementsIndexes.push(_elements.length - 1);
}

We also have to wait for View to init, so we should call this function inside "AfterViewInit" lifecycle hook

  ngAfterViewInit() {
    // Its just to prevent "checking error", I don't have time to 
       resolve this :)
    setTimeout(() => {
       this.checkLastElements(this.els.map((_element) => _element.el));
    }, 0);
  }

setTimeout is used because Angular was checking variables before they've changed. It wasn't critical bug, however it's the simplest way to resolve this warning/error message in console.

The last "tweak" would be checking "last elements" on window resize event. Angular helps us a lot with this task, and you can simply call our checkLastElements function in our HostListener

  // Handle resize window event
  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.checkLastElements(this.els.map((_element) => _element.el));
  }

full stackblitz example:

https://stackblitz.com/edit/angular-ivy-jskkaf?file=src/app/app.component.ts

However, for example if you have some "static container" like in bootstrap-css .container class, you might want to use css pseudo element :nth-child/:nth-of-type and @media.

CodePudding user response:

You can use let isLast = last in ngFor and send it as a parameter to the component.

  • Related