Ng-click не работает из динамически генерируемого 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>'
);
Angular Script
$scope.create = function() {
alert("Hi");
};
Здесь функция, вызываемая в части контроллера AngularJS, не получает триггер из события ng-click. Html успешно добавляется, но ng-click не работает. Скажите мне, как решить проблему.
Ответы
Ответ 1
Не идеальное решение, все же!!! - просто показать, как можно выполнить динамическую компиляцию.
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
Не используйте контроллер для манипуляции dom - это нужно делать с помощью директив
Ответ 2
Чтобы заставить ng-click
работать, нам нужно скомпилировать этот источник, используя $compile
service. Угловой должен знать о новом сгенерированном 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>
BTW, теперь вы можете использовать ту же директиву над своим кодом и скомпилировать любой динамический HTML.
Ответ 3
вы можете использовать angular.element(this).scope()
без использования ng-click
и измените
'<button id="createHost" class="btn btn-mini btn-success" data-ng-click="create()"><b>Create</b></button>'
To
'<button id="createHost" class="btn btn-mini btn-success" onclick="angular.element(this).scope().create()"><b>Create</b></button>'
хорошо
Ответ 4
Мне нужно было, чтобы Cordova открыла динамическую ссылку в новом окне, поэтому моим решением было поместить ng-click на родительский элемент и посмотреть на event.target, чтобы увидеть, на что было нажато:
<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');
}
})
Ответ 5
вам нужно добавить службу компиляции $здесь, которая привяжет директивы angular, такие как ng-click, к области вашего контроллера. Что-то вроде:
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());