search

Home  >  Q&A  >  body text

angular.js - Angular two-way binding is broken!

Paste the code first:

controller:

.controller('FoldController', ['$scope', function ($scope){
    $scope.isFolded = true;   //  标志是否折叠的状态
}])

directive:

.directive('fold', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {

            // 只要点击其中的内容,让其折叠回去
            element.on('click',function () {  
                scope.isFolded = true;
                element.slideUp();
                console.log(scope);             
            });

            // 折叠的函数                
            function toggleFold(isFold) {

                isFold ? element.slideUp() : element.slideDown();
            }       

            // 监视是否折叠,即controller里定义的标志
            scope.$watch(attrs.fold, function (isFold) {
                toggleFold(isFold);
            });
        }
    }
})

html:

<nav class="navbar navbar-default" ng-controller="FoldController">
    <p class="container">
        <p class="navbar-header">
            <button type="button" class="navbar-toggle"
             ng-click="isFolded=!isFolded">  
            //  主要是这里  点击后toggle折叠的标志

                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>

            <a href="#/index" class="navbar-brand">Index {{isFolded}}</a>
                                          // 为了方便测试,我将折叠表示显示出来
        </p>
                                           // 这里用directive控制
        <p class="navbar-collapse collapse" fold="isFolded">
            <ul class="navbar-nav nav">
                <li class="active"><a href="#/index">index</a></li>
                <li><a href="#/about">about</a></li>
                <li><a href="#/contact">contact</a></li>
                <li><a href="#/chatroom">chatroom</a></li>
            </ul>
        </p>

    </p>
</nav>  

Effect:

When folded

When unfolded

Preliminary submission completed, my expectation is:

When it is unfolded, click on the folded area to fold it back, and change the scope.isFold folding flag to restore it to its original state,

The question is:

There will be a bug, that is, I modified the value of scope.isFold and verified that the value of scope was changed, but the original value is still on the page, that is, the two-way binding is invalid. See the picture below

From the display in the picture, the folding area has been folded. The scope.isFold output below is also normal true, but the value at the top of the page is false. I have verified the dom element and it is correct. I have verified the controller. It is correct with the value of scope.isFold in the directive. Only this page is correct. This situation happens erratically, which is quite depressing. Can someone check it out? . .

伊谢尔伦伊谢尔伦2784 days ago936

reply all(4)I'll reply

  • phpcn_u1582

    phpcn_u15822017-05-15 16:54:42

    Add $scope.$apply to your event handler

    reply
    0
  • PHP中文网

    PHP中文网2017-05-15 16:54:42

     <p class="navbar-collapse collapse" fold ng-model="isFolded">
                <ul class="navbar-nav nav">
                    <li class="active"><a href="#/index">index</a></li>
                    <li><a href="#/about">about</a></li>
                    <li><a href="#/contact">contact</a></li>
                    <li><a href="#/chatroom">chatroom</a></li>
                </ul>
            </p>
    

    js

    .directive('fold', function () {
        return {
            require: 'ngModel',
            restrict: 'A',
            link: function (scope, element, attrs) {
    
                // 只要点击其中的内容,让其折叠回去
                element.on('click',function () {  
                    scope.isFolded = true;
                    element.slideUp();
                    scope.$digest();
                    console.log(scope);             
                });
       .....
         scope.$watch('isFolded', function (isFold) {
                    toggleFold(isFold);
                });
    
    

    reply
    0
  • 为情所困

    为情所困2017-05-15 16:54:42

    The solution is:

    After operating the dom element and modifying the attribute value on the scope, scope.$apply updates the view

    element.on('click', function() {
        pe.isFolded = !scope.isFolded;          
        element.slideUp();
        scope.$apply();
    })
    

    reply
    0
  • 黄舟

    黄舟2017-05-15 16:54:42

    In fact, many people have a misunderstanding, that is, they still use elemnet.on event monitoring in the link function,
    Why not use ngClick and write a scope.click function in the link?

    Unless you use a third-party jQuery plug-in

    reply
    0
  • Cancelreply