2013-12-09 132 views
0

我有一個指令,我在attrs中傳遞,然後在指令中監視它。一旦attrs被更改,就會發生動畫。當$watch被觸發時,我的attrs始終未定義。

App.directive('resize', function($animate) { 
    return function(scope, element, attrs) { 
    scope.$watch(attrs.resize, function(newVal) { 
     if(newVal) { 
     $animate.addClass(element, 'span8'); 
     } 
    }); 
    }; 
}); 

這裏是我的測試:

describe('resize', function() { 
    var element, scope; 
    beforeEach(inject(function($compile, $rootScope) { 
    var directive = angular.element('<div class="span12" resize="isHidden"></div>'); 
    element = $compile(directive)($rootScope); 
    $rootScope.$digest(); 
    scope = $rootScope; 
    })); 

    it('should change to a span8 after resize', function() { 
    expect($(element).hasClass('span12')).toBeTruthy(); 
    expect($(element).hasClass('span8')).toBeFalsy(); 
    element.attr('resize', 'true'); 
    element.scope().$apply(); 
    expect($(element).hasClass('span8')).toBeTruthy(); 
    }); 
}); 

attrs的變化,我的觀察家newValue是不確定的,因此沒有任何反應。我需要做些什麼來完成這項工作?這裏有一個plunker

+0

你能爲此做一個小提琴嗎? – kubuntu

+0

而不是'element.attr('resize','true');',嘗試將該行更改爲'element.scope()。resize = true;'。那樣有用嗎? – tennisgent

+0

不,那沒用。我已經添加了一個運動員。 – jhamm

回答

1

您沒有看到attrs.resize的價值;您正在觀察attrs.resize指向的值,而測試用例中的作用域成員名爲isHidden。這不存在,因此undefined

爲您阿勒想做什麼,下面將工作:

App.directive('resize', function($animate) { 
    return function(scope, element, attrs) { 
     scope.$watch(
      // NOTE THE DIFFERENCE HERE 
      function() { 
       return element.attr("resize"); 
// EDIT: Changed in favor of line above... 
//    return attrs.resize; 
      }, 
      function(newVal) { 
       if(newVal) { 
        $animate.addClass(element, 'span8'); 
       } 
      } 
     ); 
    }; 
}); 

編輯:看來,attrs對象不得到從DOM更新更新的無插值值。所以你必須觀看element.attr("resize")。我擔心這不是有效的,但...看到分叉plunk:http://plnkr.co/edit/iBNpha33e2Xw8CHgWmVx?p=preview

+2

在這種情況下,我會使用'attrs。$ observe'。 – package

+0

我複製並粘貼了你的代碼,我的指令,它仍然沒有工作。我需要在測試中改變某些東西嗎? – jhamm

+0

@package我對'$ observe'的反對是它應該看*插值*值。看起來'attrs'對象不會從DOM更新中更新非插值值。更新答案... –

0

這是我能夠使這個測試工作。我將一個變量作爲attr傳遞給該指令。變量名稱是isHidden。這是我的測試與正在工作的更新的代碼。

describe('resize', function() { 
    var element, scope; 
    beforeEach(inject(function($compile, $rootScope) { 
    var directive = angular.element('<div class="span12" resize="isHidden"></div>'); 
    element = $compile(directive)($rootScope); 
    $rootScope.$digest(); 
    scope = $rootScope; 
    })); 

    it('should change to a span8 after resize', function() { 
    expect($(element).hasClass('span12')).toBeTruthy(); 
    expect($(element).hasClass('span8')).toBeFalsy(); 
    element.scope().isHidden = true; 
    scope.$apply(); 
    expect($(element).hasClass('span8')).toBeTruthy(); 
    }); 
}); 

我可以通過連接到element範圍來訪問變量isHidden。在更改變量後,我必須運行$digest進行更新,然後全部變爲金色。

我覺得我應該可能在這裏使用$observe,正如package所述。我會看看,並在我的工作時添加評論。

0

由於尼科斯指出的問題是,你不看attrs.resize的值,因此你可以嘗試做的是:

創建一個變量來保存你的數據並創建這些$手錶功能:

var dataGetter; 

scope.$watch(function() { 
    return attrs.resize; 
}, function (newVal) { 
    dataGetter = $parse(newVal); 
}); 

scope.$watch(function() { 
    return dataGetter && dataGetter(scope); 
}, function (newVal) { 
    // Do stuff here   
}); 

我應該在這裏發生的是,角的$parse功能應該評估attrs.resize,並返回一個函數像this。然後你通過它的範圍,並做一些事情。只要attrs.resize只是一個布爾值,那麼我希望第二個監視表達式中的newVal應該是一個布爾值。

相關問題