angularjs:控制器范围属性不从控制器更新

时间:2014-11-13 22:45:09

标签: angularjs

我正在完成面包屑系统的紧凑实现,它支持弹出窗口和制表符管理。

    <div>
        <a href="" ng-click="breadcrumbs.back()">&lt; BACK</a> | Showing <em>'{{currentTab}}'</em>
    </div>
    <div
        class="popover"
        ng-repeat="p in popovers">
        <div>
            Popover name: {{p.displayName}}
        </div>
        <div ng-repeat="t in p.tabs" 
            class="tab"
            ng-class="$parent.currentTab==t.name?'selected':''"
            ng-click="$parent.$parent.currentTab=openTab(t.name)">
            {{t.name}}
        </div>
        <div  ng-repeat="t in p.tabs" 
            class="tabContent" 
            ng-class="currentTab==t.name?'selected':''">
            <p>{{t.displayName}}</p>
        </div>
    </div>
    <hr>
    <p>currentTab={{currentTab}}</p>
    <p>Breadcrumbs : {{breadcrumbs.urls.length}} levels</p>
    <ol>
        <li ng-repeat="url in breadcrumbs.urls">
            — {{$index}}: {{url.url}} | {{url.tab}}
        </li>
    </ol>

app.controller('myCtrl', function ($scope, $location, $http) {

    $scope.currentTab = $scope.currentTab||'Tab2';

    console.log("========= controller started =========");
    console.log("currentTab is '"+$scope.currenTab+"'");

    $scope.openTab = function(tab) {
        $scope.breadcrumbs.openUrl($scope.getPage()+"?openTab="+tab);
        return tab;
    };

    $scope.getPage = function() {
        //console.log("getPage() returns "+$location.path());
        return $location.path();
    };

        //-- Breadcrumb management

    $scope.breadcrumbs = {
        urls:[],
        push: function(url){
            this.urls.push(url);
        },
        back: function(){
            if (this.urls.length<1) {
                console.log("Breadcrumb: *** error back() requested but no URLs stored. Ignoring…");
                return;
            }

            var current =  this.urls[this.urls.length-1];

            // pull the current url out of the breadcrumbs stack
            this.urls.splice(-1);

            var target =  this.urls.length?this.urls[this.urls.length-1]:{url:'home', popup:null};
            openPopupOnLoad = target.popup;

            console.log("Breadcrumb: back from url "+current.url+" is asked");
            this.log("back(url "+target.url+", popup "+target.popup+", tab "+target.tab+")");

            if (current.url==target.url) {
                //$timeout(function(){
                    $scope.currentTab = target.tab;
                    $scope.$apply($scope.currentTab);
                    console.log("Breadcrumb: stay on the url "+target.url+" but set currentTab to "+$scope.currentTab);
                    //},300);
            }
            else {
                openTabOnLoad   = target.tab;
                console.log("Breadcrumb: back to url "+target.url+" (set openTabOnLoad to "+openTabOnLoad);
                $location.url(target.url);
            }
        },

        registerOpenTab: function(tab) {
            var url = $scope.getPage(); 
            if (url.substr(0,1)=='/') url = url.substr(1);

            console.log("::::: Breadcrumbs --- registerOpenTab tab "+tab+" from url "+url);

            // push target
            var target = {url: url, popup: null, tab: tab};
            this.push(target);

            this.log("registerOpenTab("+tab+")");
        },
        openUrl: function(fullUrl) {
            openPopupOnLoad = null;
            //openTabOnLoad = null;

            // look at target url if popup is requested to open?
            var popup = null;
            var tab = null;

            var url = fullUrl;
            var i = fullUrl.indexOf("?");
            if (i!=-1) {
                url = url.substr(0,i);
            }
            if (url.substr(0,1)=='/') url = url.substr(1);

            console.log("::::: Breadcrumbs --- asked to openUrl "+fullUrl);

            i = fullUrl.indexOf("openPopup=");
            if (i!=-1) {
                popup = fullUrl.substr(i+10);
                i = popup.indexOf("&");
                if (i!=-1) {
                    popup = popup.substr(0,i);
                }
            }


            i = fullUrl.indexOf("openTab=");
            if (i!=-1) {
                tab = fullUrl.substr(i+8);
                i = tab.indexOf("&");
                if (i!=-1) {
                    tab = tab.substr(0,i);
                }
            }


            // get current page
            var current = this.urls.length?this.urls[this.urls.length-1]:null;

            if (!current) {
                current = {url: $scope.getPage()};
                if (current.url.substr(0,1)=='/') current.url = current.url.substr(1);
            }


            console.log("::::: Breadcrumbs --- got url "+url+" with popup "+popup+" and tab "+tab+"(current url is "+(current?current.url:null)+")");

            // - handle potential popup
            // if target url is same page…
            if (popup) {
                if (current.url==url) {
                //this.log("openUrl("+url+", "+popup+")");

                    console.log("::::: Breadcrumbs --- already on the url "+url+" only open popup "+popup);
                    $scope.openPopover("#"+popup);
                    return;
                }
                else {
                    openPopupOnLoad = popup;
                    console.log("::::: Breadcrumbs --- recorded to open popup on load "+popup);
                }
            }

            // - handle potential tab
            if (tab) {
                //$scope.currentTab = openTabOnLoad = tab;
                console.log("::::: Breadcrumbs --- recorded to open tab on load "+tab);
                url +="?openTab="+tab;
            }

            // - push target
            var target = {url: url, popup: popup, tab: tab};
            this.push(target);

            console.log("::::: Breadcrumbs --- have to redirect to url "+url+" to open popup "+popup+ " or tab "+tab);
            this.log("openUrl("+url+", "+popup+", "+tab+")");

            $location.url(url);
        },

        log: function(text) {
            text = text||" (unknown call origin)";
            console.log("::::: Breadcrumbs -----------------------------------+");
            console.log("::::: Breadcrumbs --- > log("+text+")");
            for (var i in this.urls) {
                var t = this.urls[i];
                console.log("::::: Breadcrumbs --- "+i+" url: "+t.url+"\tpopup: "+t.popup+"\ttab: "+t.tab);
            }
            console.log("::::: Breadcrumbs ---[openPopupOnLoad\t="+openPopupOnLoad+"] <");
            console.log("::::: Breadcrumbs ---[openTabOnLoad\t="+openTabOnLoad+"] and currentTab set to "+$scope.currentTab+"<");
            console.log("::::: Breadcrumbs -----------------------------------+");
        }
    };


});

代码运行良好,除了当我运行back()作用域方法时,虽然currentTab在控制器中更新,但它不会反映在HTML部分中。尽管做了很多实验,我仍然陷入困境。

我给你一个jsFiddle在那里玩:http://jsfiddle.net/stephanedeluca/smxt8d1e/

1 个答案:

答案 0 :(得分:0)

工作小提琴 - http://jsfiddle.net/smxt8d1e/22/

这里做了几件事......

1。)将初始状态作为第一个条目推送到urls数组

// line 32
if (this.urls.length==1) {...}

// line 205
$scope.openTab($scope.currentTab);

2.。)删除了$apply声明

// line 51
//$scope.$apply($scope.currentTab);

3。)即使在$scope.currentTab

时设置current.url!=target.url
// line 58
$scope.currentTab = openTabOnLoad;

据我所知,标签现在可以正常切换。