2013-12-09 2 views
0

У меня есть директива, в которой я передаю код attrs, а затем он отображается в директиве. После изменения attrs происходит анимация. Мой attrs всегда не определен, когда запускается $watch.

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'); 
       } 
      } 
     ); 
    }; 
}); 

EDIT: кажется, что attrs объект делает НЕ обновляется от обновлений DOM для не интерполированное значения. Поэтому вам нужно будет посмотреть element.attr("resize"). Я боюсь, что это не эффективно, хотя ... См. Forked plunk: http://plnkr.co/edit/iBNpha33e2Xw8CHgWmVx?p=preview

+2

Я бы использовал 'attrs. $ Observ' в этом случае. – package

+0

Я скопировал и вставил ваш код для моей директивы, и он все еще не работал. Мне нужно что-то изменить в тесте? – jhamm

+0

@package Мое возражение с '$ observ' заключается в том, что он должен смотреть * интерполированные * значения. Кажется, что объект 'attrs' делает * NOT * обновляться из обновлений 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(); 
    }); 
}); 

Я могу получить доступ к переменной isHidden через прицел, который прилагается к element. После того, как я изменил переменную, мне нужно запустить $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 во втором выражении watch должно быть логическим, я надеюсь.

Смежные вопросы