2013-10-09 2 views
43

HTMLнг клик не работает с динамически генерируемой HTML

<table data-ng-table="tableParams" class="table table-bordered table-hover " style="border-collapse:collapse" data-ng-init="host.editSave = false" > 
    <tr id="newTransaction"> 
    </tr> 
    <tr data-ng-repeat="host in hosts|filter:search:strict" > 
     <td class="hostTableCols" data-ng-hide="host.editSave">{{host.hostCd}}</td> 
     <td class="hostTableCols" data-ng-hide="host.editSave">{{host.hostName}}</td> 
    </tr> 
</table> 

Jquery

$('#newTransaction').append(
'<td contenteditable><input type="text" class="editBox" value=""/></td>'+ 
'<td contenteditable><input type="text" class="editBox" value=""/></td>'+ 
'<td>'+ 
    '<span>'+ 
     '<button id="createHost" class="btn btn-mini btn-success" data-ng-click="create()"><b>Create</b></button>'+ 
    '</span>'+ 
'</td>' 
); 

Угловая Сценарий

$scope.create = function() { 
     alert("Hi"); 
    }; 

Здесь диафрагменное unction, вызываемый в части контроллера AngularJS, не получает триггер от события ng-click. Html успешно добавляется, но ng-click не работает. Скажите мне решения, чтобы сделать его работу

+1

вам нужно скомпилировать новые элементы dom для работы с угловыми элементами ... вы делаете эту манипуляцию в директиве/контроллере, где у вас есть доступ к области –

+0

@ArunPJohny: Я вызываю эту функцию с контроллера. Но где я должен поместить функцию компиляции? В директиве ?? –

+0

Я не знаю о конкретном сценарии, но вы можете сделать что-то подобное с помощью 'ng-include' и шаблонов. – Chandermani

ответ

38

Не идеальное решение, все еще !!! - просто чтобы показать, как динамическая компиляция может быть сделано

app.controller('AppController', function ($scope, $compile) { 

    var $el = $('<td contenteditable><input type="text" class="editBox" value=""/></td>' + 
     '<td contenteditable><input type="text" class="editBox" value=""/></td>' + 
     '<td>' + 
     '<span>' + 
     '<button id="createHost" class="btn btn-mini btn-success" data-ng-click="create()"><b>Create</b></button>' + 
     '</span>' + 
     '</td>').appendTo('#newTransaction'); 
    $compile($el)($scope); 

    $scope.create = function(){ 
     console.log('clicked') 
    } 
}) 

Демо: Fiddle

Не используйте контроллер для йот манипуляции - это должно быть сделано с помощью директив

+0

Я уже пробовал этот метод и не знал о компиляции $ ... Так что попробовал это из jQuery –

+1

@MaximShoustin: Да не следует ли нам манипулировать DOM с контроллера ?? Любые причины? –

+4

@KiranKumar Удобство использования, четкость кода, обслуживание. Контроллер должен быть связан с бизнес-логикой, а не с интерфейсом. –

32

Чтобы ng-click работать мы должны скомпилировать этот источник с помощью $compile службы. Angular должен знать о новом сгенерированном HTML, и поэтому этот HTML должен быть включен в цикл digest, чтобы вызвать ng-click и другие события.

См Fiddle

Создать "составитель":

.directive('compileData', function ($compile) { 
    return { 
    scope: true, 
    link: function (scope, element, attrs) { 

     var elmnt; 

     attrs.$observe('template', function (myTemplate) { 
     if (angular.isDefined(myTemplate)) { 
      // compile the provided template against the current scope 
      elmnt = $compile(myTemplate)(scope); 

      element.html(""); // dummy "clear" 

      element.append(elmnt); 
     } 
     }); 
    } 
    }; 
}); 

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

.factory('tempService', function() { 
    return function() { 
    return '<td contenteditable><input type="text" class="editBox" value=""/></td>'+ 
      '<td contenteditable><input type="text" class="editBox" value=""/></td>'+ 
      '<td>'+ 
       '<span>'+ 
     '<button id="createHost" class="btn btn-mini btn-success" data-ng-click="create()"><b>Create</b></button>'+ 
       '</span>'+ 
      '</td>'; 
    }; 
}); 

И, наконец, назвать это нравится:

<div compile-data template="{{mainPage}}"></div> 

в контроллере:

$scope.newTransaction= tempService(); 

Для примера должно быть что-то вроде:

<table data-ng-table="tableParams" class="table table-bordered table-hover " style="border-collapse:collapse" data-ng-init="host.editSave = false" > 
    <tr compile-data template="{{newTransaction}}"> 
    </tr> 
    <tr data-ng-repeat="host in hosts|filter:search:strict" > 
     <td class="hostTableCols" data-ng-hide="host.editSave">{{host.hostCd}}</td> 
     <td class="hostTableCols" data-ng-hide="host.editSave">{{host.hostName}}</td> 
    </tr> 
</table> 

Кстати, сейчас вы можете использовать ту же самую директиву над вашим кодом и компилировать любой динамический HTML.

+0

Должен ли я реализовать добавление html из директивы, а не выполнение jQuery? –

+1

Как я показал в своем примере, используйте Сервис и добавьте в контроллер '$ scope.newTransaction = tempService();' –

+0

@KiranKumar добавил Fiddle, чтобы вы могли зацикливаться, как это работает. –

3

I необходимо, чтобы Cordova открыла динамическую ссылку в новом окне, поэтому моим решением было поместить ng-click на родительский элемент и посмотреть на событие.цель, чтобы увидеть, что нажал на:

<p ng-bind-html="foo.barhtml" ng-click="generalClick($event)"></p> 

затем

.controller('FooCtrl', function ($scope) { 
    var html = '<a href="http://www.google.com">google.com</a>'; 

    $scope.foo.barhtml = html.replace(/href/g, 'data-href'); 

    $scope.generalClick = function(event){ 
     // have Cordova open the link in a browser window 
     window.open(event.target.attributes['data-href'].value, '_system'); 
    } 
}) 
2

вам нужно добавить $ компилировать услугу здесь, что будет связывать угловые директивы как нг щелкните на ваш контроллер scope.Something как:

var divTemplate = '..your div template'; 
var temp = $compile(divTemplate)($scope); 

Затем добавить его в HTML:

angular.element(document.getElementById('foo')).append(temp); 

Вы можете также связать события в DIV следующим образом:

var div = angular.element("divID"); 
div.bind('click', $scope.addPhoto()); 
+0

Не будет работать, если вы добавите HTML-код внутри службы по какой-либо причине. – trainoasis

10

вы можете использовать angular.element(this).scope() без использования нг нажмите

и изменить

'<button id="createHost" class="btn btn-mini btn-success" data-ng-click="create()"><b>Create</b></button>'

Для

'<button id="createHost" class="btn btn-mini btn-success" onclick="angular.element(this).scope().create()"><b>Create</b></button>' является хорошим

+0

короткий и рабочий (y) –

+0

мы можем сделать это без ограничений. Я объявлял свой всплывающий шаблон при создании всплывающего окна на заводе. – MobileEvangelist

+0

Как отправить параметры init? – Sana

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