Содержание Дети не получают никаких значений (Angular 6) - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь написать модуль Drag and Drop, который использует директивы, прикрепленные к различным элементам.Пока что я могу правильно перемещать объекты и связываться с событиями click, drag и drop (я их создал).Сейчас я пытаюсь ограничить область, в которую можно перетаскивать объекты (директива подвижной области).Если я присоединяю это к div и у меня есть вложенные div с помощью директивы movable, я смогу получить вложенные div с декоратором ContentChildren.Как вы можете видеть, в коде директивы подвижной области в ngAfterContentInit я записываю в консоль значения, найденные ContentChildren.Это всегда выводит массив длины 0. Я не уверен, что мне не хватает.Использование всех пакетов Angular 6.1.8 и cli для компиляции и обслуживания.Любая помощь приветствуется ![enter image description here] 1 (я ожидаю, что захваченное окно останется в коробке).

app.component.html

<div class="jumbotron">
  <h1 class="display-4">Drag and Drop Module</h1>
  <p class="lead">This page is designed to show you how to use the features of the drag and drop module.</p>
</div>

<div class="container-fluid">
  <div class="row">
    <div class="col-12">
      <h6>Draggable Directive</h6>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <p>The Draggable Directive is simply used as a base directive to let everyone know when the following events occur: Clicked, Dragging, Scrolling While Dragging, Dropped.</p>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <p>Status: {{DraggableStatus}}</p>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <div class="box" appdraggable (dragStart)="DraggableStatus = 'Clicked'" (dragMove)="DraggableStatus = 'Dragging'" (dragScroll)="DraggableStatus = 'Scrolling While Dragging'" (dragEnd)="DraggableStatus = 'Dropped'">
        Drag Me
      </div>
    </div>
  </div>
</div>
<div class="container-fluid">
  <div class="row">
    <div class="col-12">
      <h6>Movable Directive</h6>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <p>The Movable Directive allows the object to move around the screen.  Options include stickyX, stickyY, and reset</p>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <div class="box" appmovable>
        No Inputs
      </div>
      <div class="box" [stickyX]="true" appmovable>
        Sticky X
      </div>
      <div class="box" [stickyY]="true" appmovable>
        Sticky Y
      </div>
      <div class="box" [stickyY]="true" [stickyX]="true" appmovable>
        Sticky Both?
      </div>
      <div class="box" [appMovableReset]="true" appmovable>
        Reset
      </div>
    </div>
  </div>
</div>
<div class="container-fluid">
  <div class="row">
    <div class="col-12">
      <h6>Movable Area</h6>
    </div>
  </div>
  <div class="row">
    <div class="area" appmovablearea>
      <div appmovable>
        Trapped
      </div>

    </div>
  </div>
</div>

app.component.ts

import { AfterContentInit, ContentChildren, Directive, ElementRef, QueryList, ViewChildren, AfterViewInit, ContentChild, Component, AfterViewChecked } from '@angular/core';
import { MovableDirective } from './Directives/DragAndDrop/Directives/Movable.Directive';
import { Subscription } from 'rxjs';

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

  DraggableStatus: string = 'None';

  trappedBoxes = ['Trapped 1', 'Trapped 2'];
}

movablearea.directive.ts

    import { AfterContentInit, ContentChildren, Directive, ElementRef, QueryList } from '@angular/core';
import { MovableDirective } from './movable.directive';
import { Subscription } from 'rxjs';

interface Boundaries {
  minX: number;
  maxX: number;
  minY: number;
  maxY: number;
}

@Directive({
  selector: '[appmovablearea]'
})
export class MovableAreaDirective implements AfterContentInit {
  @ContentChildren(MovableDirective) movables: QueryList<MovableDirective>;

  private boundaries: Boundaries;
  private subscriptions: Subscription[] = [];

  constructor(private element: ElementRef) { }

  ngAfterContentInit(): void {
    console.log(this.movables);
    this.movables.changes.subscribe(() => {
      this.subscriptions.forEach(s => s.unsubscribe());

      this.movables.forEach(movable => {
        this.subscriptions.push(movable.dragStart.subscribe(() => this.measureBoundaries(movable)));
        this.subscriptions.push(movable.dragMove.subscribe(() => this.maintainBoundaries(movable)));
      });
    });

    this.movables.notifyOnChanges();
  }

  private measureBoundaries(movable: MovableDirective) {
    const viewRect: ClientRect = this.element.nativeElement.getBoundingClientRect();
    const movableClientRect: ClientRect = movable.element.nativeElement.getBoundingClientRect();

    this.boundaries = {
      minX: viewRect.left - movableClientRect.left + movable.position.x,
      maxX: viewRect.right - movableClientRect.right + movable.position.x,
      minY: viewRect.top - movableClientRect.top + movable.position.y,
      maxY: viewRect.bottom - movableClientRect.bottom + movable.position.y
    };
  }

  private maintainBoundaries(movable: MovableDirective) {
    movable.position.x = Math.max(this.boundaries.minX, movable.position.x);
    movable.position.x = Math.min(this.boundaries.maxX, movable.position.x);
    movable.position.y = Math.max(this.boundaries.minY, movable.position.y);
    movable.position.y = Math.min(this.boundaries.maxY, movable.position.y);
  }
}

movable.directive.ts

import { Directive, ElementRef, HostBinding, HostListener, Input } from '@angular/core';
import { DraggableDirective } from './draggable.directive';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';

interface Position {
  x: number,
  y:number
}

@Directive({
  selector: '[appmovable]'
})
export class MovableDirective extends DraggableDirective {
  //Variables
  position: Position = { x: 0, y: 0 };
  startPosition: Position;
  startingScroll: number = window.pageYOffset;

  @Input('appMovableReset') reset = false;  //Resets objects position if dragged.
  @Input('stickyX') stickyX = false;  //Doesnt move horizontally
  @Input('stickyY') stickyY = false;  //Doesnt move vertically.

  constructor(private sanitizer: DomSanitizer, public element:ElementRef) {
    super(element);
  }

  @HostBinding('style.transform') get transform(): SafeStyle {  //This method actually does the moving with a CSS transform
    return this.sanitizer.bypassSecurityTrustStyle(
      `translateX(${this.position.x}px) translateY(${this.position.y}px)`
    );
  }

  @HostListener('dragStart', ['$event']) onDragStart(event: PointerEvent): void { //Listens to the events emitted by Draggable Directive.
    this.startPosition = {
      x: event.clientX - this.position.x,
      y: event.clientY - this.position.y
    }
  }

  @HostListener('dragMove', ['$event']) onDragMove(event: PointerEvent): void {
    this.position.x = (this.stickyX ? this.position.x : event.clientX - this.startPosition.x);  //If sticky is set, don't change that value.
    this.position.y = (this.stickyY ? this.position.y : event.clientY - this.startPosition.y);
  }

  @HostListener('dragEnd', ['$event']) onDragEnd(event: PointerEvent): void {
    if (this.reset) {
      this.position = { x: 0, y: 0 };
    }
  }

  @HostListener('dragScroll', ['$event']) onDragScroll(event: Event): void {
    this.position.x = this.position.x;
    this.position.y = (this.stickyY ? this.position.y : (this.startingScroll + window.pageYOffset) - this.startPosition.y);
    this.startingScroll = window.pageYOffset;
  }

}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "demo": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/demo",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "demo:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "demo:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "demo:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              "styles.css"
            ],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "demo-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "demo:serve"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "demo"
}
...