Angular Dart: Data binding doesn't work when manipulating the controller from the outside, part two

假装没事ソ 提交于 2019-12-11 08:09:08

问题


A short background:

This example is a slightly more complicated version of my Angular Dart: Data binding doesn't work when manipulating the controller from the outside question that has been answered correctly. I only added a toggleable "show resolved comments" link to this version. Even though I initialized every variable to non-null values the problem still happens.

Full description of the actual problem:

I have two controllers nested into each other. The outer controller shows/hides the inner controller by using an ng-switch directive.

The outer controller also contains a checkbox. If this checkbox gets checked then the inner controller is made visible (via the above ng-switch directive). This checkbox works as intended.

There's also an "open" link outside the controllers. Its onclick handler calls into the outer controller and is supposed to check the checkbox via the model. The problem is that even though the model gets changed, the view doesn't get updated, unless I explicitly call scope.apply(), which I shouldn't. Even if I remove the comment before scope.apply() in my code then data binding doesn't work within InnerController.

This pattern has worked flawlessly in AngularJS but apparently doesn't in AngularDart.

I insist to this pattern or something similar because I'm in the process of integrating AngularDart into a legacy application that doesn't use data binding so I have to trigger model changes from outside the models.

Thanks in advance!

<html ng-app>
<head>
    <title>Angular.dart nested controllers</title>
</head>
<body>
<a href="#" id="open">open</a>
<div outer-controller ng-switch="outerCtrl.showInnerController">
    <input type="checkbox" ng-model="outerCtrl.showInnerController">
    <div inner-controller ng-switch-when="true">
        Your name: <input ng-model="innerCtrl.yourName">
        <br>
        Hello {{innerCtrl.yourName}}!
        <div ng-switch="innerCtrl.showResolvedComments" style="text-decoration:underline; color:blue; cursor:pointer">
            <div ng-switch-when="true" ng-click="innerCtrl.showResolvedComments = false">Hide resolved comments</div>
            <div ng-switch-when="false" ng-click="innerCtrl.showResolvedComments = true">Show resolved comments</div>
        </div>
    </div>
    <div inner-controller ng-switch-when="false">
        other controller
    </div>
</div>
<script type="application/dart">
    import "dart:html";
    import 'package:angular/angular.dart';
    import 'package:angular/application_factory.dart';

    OuterController outerController;
    @Controller(selector:'[outer-controller]', publishAs:'outerCtrl')
    class OuterController {
        bool showInnerController = false;
        Scope scope;
        OuterController(this.scope) {
            outerController = this;
        }

        void showOuterController() {
            showInnerController = true;
            //scope.apply();
        }
    }

    @Controller(selector:'[inner-controller]', publishAs:'innerCtrl')
    class InnerController {
        String yourName = 'defaultName';
        bool showResolvedComments = true;
    }

    class MyAppModule extends Module {
        MyAppModule() {
            type(InnerController);
            type(OuterController);
        }
    }

    main() {
        applicationFactory().addModule(new MyAppModule()).run();
        querySelector('#open').onClick.listen((Event event) {
            outerController.showOuterController();
        });
    }
</script>
</body>
</html>

回答1:


After some experimentation, it's look like angular listen specified event to activate ng-model, and it doesn't look every variable change, i think because it's complicated to watch every change in variable without impact performance.

You can change your approach by simulate a user click on the check box like:

 CheckboxInputElement checkBox = querySelector("input");
            if (checkBox.checked == false) {
                checkBox.click();
            }

It's maybe not the cleaner way to do this, but it works

Here the full code with the patch

<html ng-app>
<head>
    <title>Angular.dart nested controllers</title>
</head>
<body>
<a href="#" id="open">open</a>
<div outer-controller ng-switch="outerCtrl.showInnerController">
    <input type="checkbox" ng-model="outerCtrl.showInnerController">
    <div inner-controller ng-switch-when="true">
        Your name: <input ng-model="innerCtrl.yourName">
        <br>
        Hello {{innerCtrl.yourName}}!
        <div ng-switch="innerCtrl.showResolvedComments" style="text-decoration:underline; color:blue; cursor:pointer">
            <div ng-switch-when="true" ng-click="innerCtrl.showResolvedComments = false">Hide resolved comments</div>
            <div ng-switch-when="false" ng-click="innerCtrl.showResolvedComments = true">Show resolved comments</div>
        </div>
    </div>
    <div inner-controller ng-switch-when="false">
        other controller
    </div>
</div>
<script type="application/dart">
    import "dart:html";
    import 'package:angular/angular.dart';
    import 'package:angular/application_factory.dart';

    OuterController outerController;
    @Controller(selector:'[outer-controller]', publishAs:'outerCtrl')
    class OuterController {
        bool showInnerController = false;
        Scope scope;
        OuterController(this.scope) {
            outerController = this;
        }

        void showOuterController() {
            showInnerController = true;
            print("showOuterController");
            //scope.apply();
        }
    }

    @Controller(selector:'[inner-controller]', publishAs:'innerCtrl')
    class InnerController {
        String yourName = 'defaultName';
        bool showResolvedComments = true;
    }

    class MyAppModule extends Module {
        MyAppModule() {
            type(InnerController);
            type(OuterController);
        }
    }

    main() {
        applicationFactory().addModule(new MyAppModule()).run();
        querySelector('#open').onClick.listen((Event event) {
            outerController.showOuterController();
            // Added Code
            CheckboxInputElement checkBox = querySelector("input");
            if (checkBox.checked == false) {
                checkBox.click();
            }
            // End added code
        });
    }
</script>
</body>
</html>


来源:https://stackoverflow.com/questions/24677379/angular-dart-data-binding-doesnt-work-when-manipulating-the-controller-from-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!