0

Я пытаюсь создать настраиваемое событие для переключения с помощью Angular. Директива называется toggleable.Угловая директива, привязка события клика к внешнему элементу не работает

Сначала это звучит тривиально, но сложный бит заключается в том, что я хочу иметь возможность использовать любую кнопку или ссылку на странице для переключения.

Код я написал, как показано ниже

Директива

'use strict'; 

angular.module('onsComponents') 
.directive('togglable', function() { 
return { 
    restrict: 'A', 
    transclude: true, 
    scope: { 
    togglerId: '@', 
    show: '@' 
    }, 
    link: function(scope, element, attrs) { 
    if (!scope.togglerId) { 
     console.error("Toggler id must be given") 
     return 
    } 

    scope.visible = (scope.show === 'true') 
    scope.toggle = function() { 
     alert("Before " + scope.visible) 
     scope.visible = !scope.visible 
     alert("After " + scope.visible) 
    } 

    //Bind click event to given dom element 
    angular.element('#' + scope.togglerId).bind("click", function() { 
     scope.toggle() 
    }) 


    }, 
    templateUrl: 'app/components/toggler/toggler.html' 
    } 
    }) 

Шаблон

<div ng-transclude ng-show="visible"> 

</div> 

Взгляд

<a href="" id="toggleButton" >Click me to toggle</a> 
<div togglable toggler-id="toggleButton"> 
    Hey 
</div> 

Точка переключения, похоже, работает. Я вижу предупреждения при нажатии ссылки. Проблема заключается в том, что содержимое не отображается. Кажется, что ссылка на самом деле не в том же объеме с содержимым, другая область создается, когда я это делаю.

Если я перемещаю ссылку на клик в шаблоне, как показано ниже, он работает. Но это не совсем то, что я хочу.

<!-- Move the link inside template --> 
<a href="" ng-click="toggle()" >Click me to toggle</a> 
<div ng-transclude ng-show="visible"> 

</div> 

Так как же я могу достичь этого?

+0

Попробуйте вызвать 'рамки . $ apply() 'после вызова' scope.toggle() 'в прослушивателе событий. –

+0

@NikosParaskevopoulos Да, он работает после вызова области. $ Appy(). Спасибо – Bren

+0

@NikosParaskevopoulos Можете ли вы разместить это в качестве ответа? – Bren

ответ

1

Вы должны позвонить scope.$apply() каждый раз, когда вы меняете материал, который угловые часы снаружи of Angular. По вне я имею в виду события, связанные с использованием JQuery API - или любым другим способом, кроме Угловая родной ng-click и т.д.

Так что либо:

scope.toggle = function() { 
    scope.visible = !scope.visible; 
    scope.$apply(); 
} 

Или:

scope.toggle = function() { 
    scope.$apply(function() { 
     scope.visible = !scope.visible; 
    }); 
} 
2

Это angular-esque, чтобы создать две директивы и службу, которая связывает их для этой цели. В общих чертах:

app.service('toggleService', function() { 
    var toggleables = {}; 

    this.registerToggleable = function(key, f) { 
     toggleables[key] = f; 
    } 

    this.toggle = function(key) { 
     var f = toggleables[key]; 
     f(); 
    } 
}); 

app.directive('toggler', function(toggleService) { 
    return { 
     link: function(scope, elem, attrs) { 
      elem.bind("click", function() { 
       toggleService.toggle(attrs.toggler); 
       // because the event handler operates outside of angular digest cycle 
       scope.$apply(); 
      }); 
     } 
    } 
}) 

app.directive('toggleable', function(toggleService) { 
    return { 
     link: function(scope, elem, attrs) { 
      function toggle() { 
       scope.visible = !scope.visible; 
      } 

      toggleService.registerToggleable(attrs.toggleable, toggle); 
     } 
    } 
}); 

выше будет нуждаться в тонкой настройки на самом деле сделать ничего отдельно от установки переменной на сферу, но тогда вы можете использовать два так:

<a href="" toggler="foo" >Click me to toggle</a> 
<div toggleable="foo"> 
    Hey 
</div> 

Это так что вы объявляете функцию переключения на самих элементах, без магии поиска на основе ID.

+0

Более элегантное спасибо. Я попробую это и дам вам знать результат – Bren

+0

Без вызова области. $ Apply() в прослушивателе событий. Это не работает. То же самое, что и моя оригинальная проблема. Большое вам спасибо за более угловатый способ решения. – Bren

+0

Ах, конечно, я не заметил, что привязка события будет за пределами возможностей Angular! Извините, я отредактирую ответ – AlexFoxGill

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