Using jquery with dynamically created elements from angular doesnt work - javascript

Im trying to use jquery to manipulate elements created by angular, but I am not able to get it to work. I was wondering if anyone could help me out. Thanks
Here is the HTML
<div class="patients">
<tbody ng-repeat="patient in patients">
<tr>
<td>{{patient.name}}</td>
<td>{{patient.number}}</td>
<td>{{patient.date}}</td>
<td id="item-{{$index}}">{{patient.reminded}}</td>
<div class="sendreminder">
<td>
<a href="" class="btn btn-info btn-sm sendreminder" style=" background-color: #00e699; border-color:#00e699; " ng-click="post($index) " "$parent.selected = $index" id="button-{{$index}}">
<span class="glyphicon glyphicon-send"></span> Request Payment
</a>
</td>
</div>
<td>
<a href="" style="text-decoration:none; color:inherit; scale: 4" class="pe-7s-info">
</a>
</td>
</tr>
</tbody>
</div>
Here is the jquery
$(function() {
$('.patients').on('click', ".sendreminder",function(e){
alert('worked');
});
});

ng-repeat recreates DOM everytime it detects changes(and hence, all the attached events will be gone). So to reattach the events after ng-repeat finishes, you can do
<tbody ng-repeat="patient in patients" ng-init="$last && ngRepeatFinish()">
$last will be set to true if its the last item for ng-repeat
and in you controller, create ngRepeatFinish() function
$scope.ngRepeatFinish = function(){
$('.sendreminder').click(function(e){
alert('worked');
});
}
you can also make custom directives for this which is better than this, but this will suffice for a quick solution.
See this for a solution with custom directives

You should call that code immediately after you dynamically create the new element since that code sets the handler for the actual elements (when you call the function) that have class .patients, not the new ones...

i recommend you to use Angular instead of Jquery
added both methods below
//using Jquery
$('.patients').on('click', ".sendreminder", function(e) {
alert('from JQuery');
});
function TestCtrl($scope) {
$scope.patients = [{
name: 'one',
number: 1,
date: '2016-08-16',
reminded: true
}, {
name: 'two',
number: 2,
date: '2016-08-16',
reminded: true
}, {
name: 'three',
number: 3,
date: '2016-08-16',
reminded: false
}];
//using angular
$scope.post = function(i) {
alert('from Angular');
var selectedPatient = $scope.patients[i];
console.log(selectedPatient);
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app>
<div class="patients" ng-controller="TestCtrl">
<table>
<thead>
<tr>
<th>Name</th>
<th>Number</th>
<th>Date</th>
<th>Reminded</th>
<th>Request</th>
<th>Info</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="patient in patients">
<td>{{patient.name}}</td>
<td>{{patient.number}}</td>
<td>{{patient.date}}</td>
<td id="item-{{$index}}">{{patient.reminded}}</td>
<td>
<a href="" class="btn btn-info btn-sm sendreminder" style="background-color: #00e699; border-color:#00e699;" ng-click="post($index)" id="button-{{$index}}">
<span class="glyphicon glyphicon-send"></span> Request Payment
</a>
</td>
<td>
<a href="" style="text-decoration:none; color:inherit; scale: 4" class="pe-7s-info">test
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>

Related

unwanted angular value link

The picture shows an edit page, which use can add commands to the list, delete and so on. The value should be only updated to the actual array when user click update button. Below are some of my code:
$scope.editSchedule = function(index){
console.log(index);
$scope.editScheduleValue = {
name: $scope.currentSchedule[index].name,
trigger: $scope.currentSchedule[index].trigger,
repeat: $scope.currentSchedule[index].repeat,
commandList: $scope.currentSchedule[index].commandList,
scheduleIndex: index
};
var dailog = $uibModal.open({
templateUrl: 'app/partials/edit-schedule.html',
controller: editScheduleController,
size: 'lg',
scope: $scope
});
};
This is a edit button scope, which will get the actual value from curremtSchedule array.
$scope.addCommand = function(){
console.log("addCommand");
$scope.addRoom = $scope.equipment[$scope.roomSelected].name;
$scope.addEquipment = $scope.equipment[$scope.roomSelected].equipment[$scope.equipmentSelected].name;
$scope.addEquipmentCommand = $scope.equipment[$scope.roomSelected].equipment[$scope.equipmentSelected].command[$scope.commandSelected].type;
$scope.editScheduleValue.commandList.push({
room: $scope.addRoom,
equipment: $scope.addEquipment,
command: $scope.addEquipmentCommand
})
};
This is my Add command button code, which push data to editScheduleValue array.
HTML:
<tr ng-repeat="x in editScheduleValue.commandList" ui-tree-node>
<td style="width: 5%"><i class="glyphicon glyphicon-resize-vertical" ui-tree-handle></i> </td>
<td style="width: 5%">{{$index+1}}</td>
<td style="width: 30%">{{x.room}}</td>
<td style="width: 30%">{{x.equipment}}</td>
<td style="width: 30%">{{x.command}}</td>
<td>
<a class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="remove(this)">
<span class="glyphicon glyphicon-remove"></span>
</a>
</td>
</tr>
The problem that I encouter is whenever I delete, add command not only the editScheduleValue array updated, but the currentSchedule array as well, I really do not understand why is this 2 array is somehow linked. Please help~~~
Thank you.
I replace
commandList: $scope.currentSchedule[index].commandList,
With
commandList: angular.copy($scope.currentSchedule[index].commandList),
and this 2 arrays are not link anymore, I do not quite understand why it is, but here the answer for my problem.

Putting table into Bootstrap popover

I have a Bootstrap popover and I'm trying to put a table into it but then it doesn't show up when I click on it. This is the first time attempting HTML inside a popover so I'm unsure how to go about doing it correctly. Thanks!
$(function(){
$("[data-toggle=popover]").popover({
html : true,
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
});
<a role="button" class="btn btn-link btn-item black-text" data-toggle="popover" data-trigger="focus" data-placement="top" title="Currency Converter" data-content="Displayed rates are only for informational purposes and do not reflect on the actual rates you may be charged by the financial institution handling your transaction.
<table class='table table-condensed table-bordered'>
<tr><td>Euro</td><td>€79,123</td></tr>
<tr><td>GB Pound</td><td>£46,536</td></tr>
<tr><td>AU $</td><td>$123,456</td></tr>
</table>LLC accepts payment in US Dollars only. Rates do not include taxes, duties, shipping, insurance, or any other expenses associated with the purchase."><i class="fa fa-exchange"></i> Currency converter</a>
This worked for me:
$(function() {
$.fn.popover.Constructor.Default.whiteList.table = [];
$.fn.popover.Constructor.Default.whiteList.tr = [];
$.fn.popover.Constructor.Default.whiteList.td = [];
$.fn.popover.Constructor.Default.whiteList.div = [];
$.fn.popover.Constructor.Default.whiteList.tbody = [];
$.fn.popover.Constructor.Default.whiteList.thead = [];
$('[data-toggle="popover"]').popover({
html: true,
container: 'body'
})
})
Example : http://jsfiddle.net/z824fn6b/320/ use table in popover and toggle button
Popover Example
<div id="a1" class="hidden">
<div class="popover-heading">Title <span style="float:right;cursor:pointer;" class="fa fa-times" data-toggle="popover"></span></div>
<div class="popover-body">
<table style="width:100%">
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</div>
</div>
$(function() {
$("[data-toggle=popover]").popover({
html: true,
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
});
This may help:
HTML:
<div id="myPopoverContent">
<table border="1" style="width:100%">
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
jQuery:
$('[data-toggle=popover]').popover({
content: $('#myPopoverContent').html(),
html: true
}).click(function() {
$(this).popover('show');
});
Working jsFiddle: http://jsfiddle.net/ja3f6p4j/19/
Here is how I did it:
HTML:
<div class="span12" style="margin-top: 150px;width:100%">
<a tabindex="0" role="button" data-trigger="focus" class="btn-sm btn-info" data-placement="top" id="commentPopover"><i class="fa fa-comments" ></i> View</a>
<!-- Popover 2 hidden content -->
<div id="commentPopoverHiddenContent" style="display: none">
<div>
<table border="1" style="width:100%">
<tr>
<th width="30%">Comment date</th>
<th width="70%">Comment</th>
</tr>
<tr>
<td>12/03/2015 16:45</td>
<td>*Username - Testing1</td>
</tr>
<tr>
<td>12/03/2015 16:55</td>
<td>*Username - Testing2</td>
</tr>
<tr>
<td>12/03/2015 17:13</td>
<td>*Username - Testing3</td>
</tr>
</table>
</div>
</div>
<!-- Popover 2 hidden title -->
<div id="commentPopoverHiddenTitle" style="display: none">
Error comments
</div>
</div>
JQuery:
$(function(){
// Enabling Popover Example 2 - JS (hidden content and title capturing)
$("#commentPopover").popover({
html : true,
content: function() {
return $('#commentPopoverHiddenContent').html();
},
title: function() {
return $('#commentPopoverHiddenTitle').html();
}
});
});
Here is a fiddle: http://jsfiddle.net/5bsykcqt/
As nothing was working well for me and the answers were old, this did the trick:
const list = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
list.map((el) => {
let opts = {
animation: false,
}
if (el.hasAttribute('data-bs-content-id')) {
opts.content = document.getElementById(el.getAttribute('data-bs-content-id')).innerHTML;
opts.html = true;
opts.sanitizeFn = function (content) {
return content
}
}
new bootstrap.Popover(el, opts);
})
As alluded to at the bottom of this page: Bootstrap 5 Documentation
You can set your own sanitize function, so if you just return what was provided, nothing is removed. Boom
With CSS3 there is a simpler solution: you can use the following display attributes to simulate a table behavior
.popover_container{
display: table;
}
.popover_row{
display: table-row;
}
.popover_column1{
display: table-cell;
text-align: left;
}
.popover_column2{
display: table-cell;
text-align: left;
}
and then build the popover content
$popover_content = "<div class='popover_container'>
<div class='popover_row'>
<div class='popover_column1'></div>
<div class='popover_column2'></div>
</div>
</div>";
and use it in your HTML
echo ('<span class="material-symbols-outlined" data-bs-html="true" data-bs-toggle="popover" data-bs-trigger="hover" title="your titile" data-bs-content="'.$popover_content.'">youricon</span>')

Accessing element from click event in jquery widget

I am trying to make a custom widget that creates tabs .But the problem Im facing is ,I have a click event defined on clicking on one of the tabs but I am unable to access the attributes associated with that tab element (like myid="summarytab")
Here is a code snippet for the same
jquery.tabs.js
$.widget('ui.tabs', {
options: {
},
_create: function() {
alert('attaching')
var me = this
me._on('td', {
click: "_selectedTab"
})
},
_selectedTab: function(el) {
alert("coming" + el.attr('goto'))
},
_destroy: function() {
}
});
jstChking.html
<table id="tabs-container" goto="summary">
<tbody>
<tr class="a-detail-menu">
<td myid="summary" goto="summary" class="selected">
<i class="fa fa-bank deco"></i>
Summary
</td>
<td goto="applicability" myid="applicabilityTab" >
<i class="fa fa-tags deco"></i>
Applicability
</td>
<td goto="assessments" myid="assessmentTab">
<i class="fa fa-check-circle-o deco"></i>
Assessments
</td>
<td class="ignore"></td><td class="ignore"></td>
</tr>
</tbody>
</table>
<div class="a-section summary" >
<h2>HTML Markup for these tabs</h2>
content1
</div>
<div class="a-section applicability" style="display:none">
<h2>JS for these tabs</h2>
content2
</div>
<div class="a-section assessments" style="display:none">
<h2>CSS Styles for these tabs</h2>
content3
</div>
The idea is to hide all tabs and show the one that is clicked.I am trying to do that in jquery using the goto="xyz" and and show only that div. Now when i m trying to make in widget then i m not getting the attribute.Also if u have any suggestions ,that would be welcome.
Thanks in advance

AngularJS - Building a dynamic table based on a json

Given a json like this:
{
"name": "john"
"colours": [{"id": 1, "name": "green"},{"id": 2, "name": "blue"}]
}
and two regular html inputs:
<input type="text" name="name" />
<input type="text" name="color" />
<input type="submit" value="submit" />
I need to build a table with all the possible variations, ex:
John green
John blue
That means that if a user continues adding values through the inputs new rows will appear building the new variations, for instance:
I also need to have available the id to handle it, and I need that when I add new values using the inputs for instance: "Peter" "Black", I need to autofill the id (colour id) dynamically like an auto increment in mysql, resulting in something like this:
{
"colours": […...{"id": 3, "name": "black"}]
}
Is that possible? Which options do I have for doing that with angular? I'm still thinking in the jQuery way and I would like to do it in the angular way.
I took a look to hg-repeat, and used it, but I'm not figuring out how to deliver the expected result, the only thing that come to my mind was to use nested ng-repeats, but it didm´t work.
Thanks so much in advance,
Guillermo
Just want to share with what I used so far to save your time.
Here are examples of hard-coded headers and dynamic headers (in case if don't care about data structure). In both cases I wrote some simple directive: customSort
customSort
.directive("customSort", function() {
return {
restrict: 'A',
transclude: true,
scope: {
order: '=',
sort: '='
},
template :
' <a ng-click="sort_by(order)" style="color: #555555;">'+
' <span ng-transclude></span>'+
' <i ng-class="selectedCls(order)"></i>'+
'</a>',
link: function(scope) {
// change sorting order
scope.sort_by = function(newSortingOrder) {
var sort = scope.sort;
if (sort.sortingOrder == newSortingOrder){
sort.reverse = !sort.reverse;
}
sort.sortingOrder = newSortingOrder;
};
scope.selectedCls = function(column) {
if(column == scope.sort.sortingOrder){
return ('icon-chevron-' + ((scope.sort.reverse) ? 'down' : 'up'));
}
else{
return'icon-sort'
}
};
}// end link
}
});
[1st option with static headers]
I used single ng-repeat
This is a good example in Fiddle (Notice, there is no jQuery library!)
<tbody>
<tr ng-repeat="item in pagedItems[currentPage] | orderBy:sortingOrder:reverse">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.field3}}</td>
<td>{{item.field4}}</td>
<td>{{item.field5}}</td>
</tr>
</tbody>
[2nd option with dynamic headers]
Demo 2: Fiddle
HTML
<table class="table table-striped table-condensed table-hover">
<thead>
<tr>
<th ng-repeat="header in table_headers"
class="{{header.name}}" custom-sort order="header.name" sort="sort"
>{{ header.name }}
</th>
</tr>
</thead>
<tfoot>
<td colspan="6">
<div class="pagination pull-right">
<ul>
<li ng-class="{disabled: currentPage == 0}">
<a href ng-click="prevPage()">« Prev</a>
</li>
<li ng-repeat="n in range(pagedItems.length, currentPage, currentPage + gap) "
ng-class="{active: n == currentPage}"
ng-click="setPage()">
<a href ng-bind="n + 1">1</a>
</li>
<li ng-class="{disabled: (currentPage) == pagedItems.length - 1}">
<a href ng-click="nextPage()">Next »</a>
</li>
</ul>
</div>
</td>
</tfoot>
<pre>pagedItems.length: {{pagedItems.length|json}}</pre>
<pre>currentPage: {{currentPage|json}}</pre>
<pre>currentPage: {{sort|json}}</pre>
<tbody>
<tr ng-repeat="item in pagedItems[currentPage] | orderBy:sort.sortingOrder:sort.reverse">
<td ng-repeat="val in item" ng-bind-html-unsafe="item[table_headers[$index].name]"></td>
</tr>
</tbody>
</table>
As a side note:
The ng-bind-html-unsafe is deprecated, so I used it only for Demo (2nd example). You welcome to edit.
Here's an example of one with dynamic columns and rows with angularJS: http://plnkr.co/edit/0fsRUp?p=preview
TGrid is another option that people don't usually find in a google search. If the other grids you find don't suit your needs, you can give it a try, its free
Check out this angular-table directive.
<table class="table table-striped table-condensed table-hover">
<thead>
<tr>
<th ng-repeat="header in headers | filter:headerFilter | orderBy:headerOrder" width="{{header.width}}">{{header.label}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users" ng-class-odd="'trOdd'" ng-class-even="'trEven'" ng-dblclick="rowDoubleClicked(user)">
<td ng-repeat="(key,val) in user | orderBy:userOrder(key)">{{val}}</td>
</tr>
</tbody>
<tfoot>
</tfoot>
</table>
refer this https://gist.github.com/ebellinger/4399082
First off all I would like to thanks #MaximShoustin.
Thanks of you I have really nice table.
I provide some small modification in $scope.range and $scope.setPage.
In this way I have now possibility to go to the last page or come back to the first page.
Also when I'm going to next or prev page the navigation is changing when $scope.gap is crossing. And the current page is not always on first position. For me it's looking more nicer.
Here is the new fiddle example:
http://jsfiddle.net/qLBRZ/3/

EmberJS re-use same template, but displays the template twice

I am playing with Ember, and building a basic contact management app to learn Ember. I am following the Emberjs getting started guide. Only instead of doing a "to-do" app, Im doing my own thing in hopes of picking it up better.
My Router, and Routes:
App.Router.map(function() {
this.resource('users', function() {
this.resource('user', { path: ':user_id' });
this.route('motoDigitalTrue');
});
this.resource('about');
});
App.UsersRoute = Ember.Route.extend({
model: function() {
return App.User.find();
}
});
App.UsersMotoDigitalTrueRoute = Ember.Route.extend({
model: function(){
return App.User.filter(function(user) {
if (user.get('motoDigital')) {
return true;
}
});
},
renderTemplate: function(controller) {
this.render('users', {
controller:controller
});
}
});
Essentially, I have a template named 'users' that I want to reuse. This template lists all the users. I have a sorting button that when clicked, will only display the users who have the motoDigitalTrue property set to true. The sorting is correct, but it just displays another Users template, rather than re-populating the original.
My Users template:
<script type="text/x-handlebars" id="users">
<div class="span10 tableContainer">
<button class="btn btn-primary createUser" {{action createUser}}><i class="icon-plus icon-white"></i> Add a Contact</button>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">Sort<span class="caret"></span></a>
<ul class="dropdown-menu">
{{#linkTo 'users.motoDigitalTrue' activeClass="selected"}}Receiving MOTO Digital{{/linkTo}}
</ul>
</div>
<div class="tableScrollable">
<table class="table table-striped">
<thead>
<tr>
<th class="nameHead">Name</th>
<th class="companyHead">Company</th>
<th class="emailHead">Email</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">&nbsp</td>
<td class="company">&nbsp</td>
<td class="email">&nbsp</td>
</tr>
{{#each model}}
<tr>
<td class="name"><i class="icon-user"></i> <strong>{{#linkTo 'user' this }}{{firstName}} {{lastName}}{{/linkTo}}</strong></td>
<td class="company">{{company}}</td>
<td class="email"><i class="icon-envelope"></i> <a {{bindAttr mailto="email"}}>{{email}}</a></td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
<div class="span3">
{{#if isCreateUser}}
<div class="well">
{{partial 'users/createUser'}}
<button {{action 'saveUser'}} class="btn btn-primary"><i class="icon-ok icon-white"></i> Save</button>
</div>
{{else}}
{{outlet}}
{{/if}}
</div>
</script>
I have been unable to find an answer, and any help would be appreciated!
I guess in your case to reuse templates, you should try using a partial, have a look here.
For example, rename your users template to _users
<script type="text/x-handlebars" data-template-name='_users'>
...
</script>
and then use the partial helper to render it
{{partial users}}
Note that {{partial}} takes the template to be rendered as an argument, and renders that template in place. This means that it does not change context or scope. It simply renders the given template with the current scope.
Hope it helps.

Categories

Resources