Like a scrollTop div whose content is controlled by AngularDart?

I have a divcontaining chat history. I would like the content to divscroll when it fills. I have work using jQuery in another project, but what would be the correct way for AngularDart to achieve this?

Simplification of a bit, in my HTML I

<div class="chatHistory">{{ctrl.text}}</div>

(using style white-space:pre), and in my controller I have a method

void addToChatHistory(String msg) {
  text += msg;
  var elt = querySelector(".chatHistory");
  elt.scrollTop = elt.scrollHeight;
}

Questions:

  • This code scrolls the contents div, but not enough, because it installs too quickly scrollTop; that is, before it .chatHistorycan be updated using Angular.
  • Also, this (partial) solution doesn't really like Angular in style using querySelector.

watch text, . ?

+2
3

Timer.run :

Timer.run(() => elt.scrollTop = elt.scrollHeight);

, , querySelector :

MyController(Element e) : elt = e.querySelector('.chatHistory');
+1

EDIT

, : http://pub.dartlang.org/packages/bwu_angular
-------

/Decorator, NgEventDirective, div. scrollTop.

.

Angular " " ( ), https://code.google.com/p/dart/issues/detail?id=18062, , .

, Dartium , ( Dart VM: 1.4.0-dev.4.0 ( 1 04:06:09 2014) "linux_x64" ). , .

( , - , )

index.html

<!DOCTYPE html>
<html ng-app>
  <head>
    <script src="packages/web_components/platform.js"></script>
    <style>
      .resize-triggers {
              visibility: hidden;
      }

      .resize-triggers, .resize-triggers > div, .contract-trigger:before {
        content: " ";
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        overflow: hidden;
      }

      .resize-triggers > div {
        background: #eee;
        overflow: auto;
      }

      .contract-trigger:before {
        width: 200%;
        height: 200%;
      }
    </style>
    <style>
      #my_element {
        height: 200px;
        overflow: scroll;
      }
    </style>
  </head>
  <body ng-cloak>
    <div>
      <div id="my_element"  style="border: 1px solid blue;">
        <div id='my_sizable' ng-observe-size></div>
      </div>
    </div>

    <script type="application/dart" src="index.dart"></script>
    <script type="text/javascript" src="packages/browser/dart.js"></script>

  </body>
</html>

index.dart

library angular_observe_resize.main;

import 'dart:async' as async;
import 'dart:html' as dom;
import 'package:angular/angular.dart' as ng;
import 'package:angular/application_factory.dart' as ngaf;

// see https://stackoverflow.com/questions/19329530
// and this bug https://code.google.com/p/dart/issues/detail?id=18062
// source from http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/

@ng.Decorator(selector: '[ng-observe-size]')
class NgObserveSizeDirective implements ng.AttachAware, ng.DetachAware {
  dom.Element _element;
  bool _hasAttacheEvent;

  NgObserveSizeDirective(this._element);

  void onSizeChange(dom.Event e) {
    _element.parent.scrollTop = _element.scrollHeight;
  }

  dom.HtmlElement _triggers;

  void resetTriggers() {
    var expand = _triggers.children[0];
    var contract = _triggers.children[_triggers.children.length - 1];
    var expandChild = expand.children[0];
    contract.scrollLeft = contract.scrollWidth;
    contract.scrollTop = contract.scrollHeight;
    expandChild.style.width = '${expand.offsetWidth + 1}px';
    expandChild.style.height = '${expand.offsetHeight + 1}px';
    expand.scrollLeft = expand.scrollWidth;
    expand.scrollTop = expand.scrollHeight;
  }

  int _resizeLastWidth;
  int _resizeLastHeight;

  bool checkTriggers() {
    return _element.offsetWidth != _resizeLastWidth ||
        _element.offsetHeight != _resizeLastHeight;
  }

  int _resizeRaf;


  void scrollListener(dom.Event e) {
    resetTriggers();
    if(_resizeRaf != null) {
      dom.window.cancelAnimationFrame(_resizeRaf);
    }
    _resizeRaf = dom.window.requestAnimationFrame((num highResTime){
      if(checkTriggers()) {
        _resizeLastWidth = _element.offsetWidth;
        _resizeLastHeight = _element.offsetHeight;
        onSizeChange(e);
      }
    });
  }

  @override
  void attach() {
    if(_element.getComputedStyle().position == 'static') {
      _element.style.position = 'relative';
    }

    _triggers = new dom.DivElement()
      ..classes.add('resize-triggers')
      ..append(new dom.DivElement()..classes.add('expand-trigger')..append(new dom.DivElement()))
      ..append(new dom.DivElement()..classes.add('contract-trigger'));
   _element.append(_triggers);

    new async.Future.delayed(new Duration(seconds: 1), () {
      //_triggers = _element.children[_element.children.length - 1];
      resetTriggers();

      dom.Element.scrollEvent.forTarget(_element, useCapture: true).listen(scrollListener);
    });
  }

  @override
  void detach() {
    _triggers.remove();
  }
}

class MyAppModule extends ng.Module {
  MyAppModule() {
    type(NgObserveSizeDirective);
  }
}

main() {
  print('main');
  ngaf.applicationFactory().addModule(new MyAppModule()).run();

  new async.Timer.periodic(new Duration(seconds: 1), (t) {
    var elt = (dom.querySelector('#my_sizable') as dom.HtmlElement);
    elt.append(new dom.Element.html('<div>${new DateTime.now()}</div>'));
  });
}
0

If you are using the AngularDart component, you can enter shadowdom, and then select the element inside it to focus. Did not find a way to get a container of shadow space.

new Future.delayed(new Duration(milliseconds: 300), () {
  var rowElement = _shadowRoot.querySelector('.step-container');
  if (rowElement != null ) {
    rowElement.scrollIntoView(ScrollAlignment.TOP);
  }
});

ShadowDom.host may work, although it is currently marked as experimental.

0
source

Source: https://habr.com/ru/post/1535263/


All Articles