Im trying to figure out if its possible to get the width of the parent my directive is going to be placed in.
Keeping it simple I have some directive my-directive which Im placing inside of a table:
<table>
<tr>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
</tr>
</table>
And inside my-directive Iwant to know the width of my parent <td> so I could display my content properly - with more or less data according to the width
Can it be done?
Update:
My HTML code:
<table class="table">
<thead>
<tr>
<td width="5%"></td>
<td width="5%"></td>
<td width="85%"></td>
</tr>
<tr>
<th>Col 5</th>
<th>Col 5</th>
<th>Col C 85</th>
</tr>
</thead>
<tbody>
<tr>
<td><trim value="Some value a"></trim></td>
<td>Some value b</td>
<td>Some value c</td>
</tr>
</tbody>
</table>
My directive:
angular.module('ui.directives', []).directive('trim', function() {
return {
restrict: 'E',
scope: {
value: '#'
},
template: "{{value | limitTo:6}}"
};
}
);
From within the template I can limit by a constant I define (or pass by, from outside. But I want to change that, to know myself, from within that directive if I should trim the text or not
Yes you can get the parent element using angular's jqlite, a subset of jquery in the link function. The link function is to provide the behavior to your directive, in this function you can get the directive element and modify it at run time according to your need.
angular.directive('myDirective', [function($document) {
return {
restrict:'E',
link: function(scope, element, attribute) {
var parent = element.parent();// will give an array
var parentWidth = parent[0].offsetWidth;
//modify/truncate your attribute.value depending upon the parentWidth.
}
}
}]);
Related
I am trying to highlight a table row if it has a tick (check mark) in one of the td’s. I am using the jQuery code below, but it will not find a td with a html symbol such as a tick (check mark). It makes no difference if I use .text() or .html(). The code works as expected if I use any other criteria such as text or numbers, but not with html symbols. Is there away round this?
$('#farm td').filter(
function(t) {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
return;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
You just need to check for the actual character (✓). jQuery acts on rendered HTML, not markup. I determined this by setting a breakpoint on the line with text() in it and looking at the values that came through.
Also:
.each() makes more sense to me here
no need to return anything in the function
no need to pass in anything (t)
console logs are far nicer than alerts for debugging
$('#farm td').each(function() {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
Mohamed-Yousef suggested a great refinement using an internal selector:
$('#farm td:contains("✓")').closest('tr').css('background-color', 'Yellow');
It's a slightly different selector as it would also match ✓ blah, for example, but maybe it's useful in your case.
https://api.jquery.com/contains-selector/
I'm trying to create a table in Angular with a dynamic number of columns and rows. I've found this easy to accomplish using the HTML table element by doing something like this:
<table class="html-table">
<tr class="headers">
<th>Name</th>
<th>Age</th>
<th>Sex</th>
<th *ngIf="columns == 4">Species</th>
</tr>
<tr>
<td>Ryan</td>
<td>30</td>
<td>M</td>
<td *ngIf="columns == 4">Human</td>
</tr>
</table>
In this example there might be some button that toggles the value of columns between 3 and 4.
Every explanation I have looked at online involves changing CSS variables, which seems like a somewhat hacky way to accomplish something that should be simple. Is there some way I can specify that something should be a new column in CSS grid rather than that having to specify the number of columns in grid-template-columns?
In Angular you can use ng-repeat to have a dynamic table
A typical example could be
<table ng-table="tableParams" class="table table-striped">
<tr ng-repeat="data in datas">
<td title="Title_Of_First_Variable">{{data.variable1}}</td>
<td title="Title_Of_Second_Variable">{{data.variable2}}</td>
<td title="Title_Of_Third_Variable">{{data.variable3}}</td>
...
</tr>
</table>
Of course with your controller you should pass your dynamic data into the correct $scope, in this case should be $scope.datas (usually an object)...maybe something like this, using NodeJS:
$http.post('route_of_your_method')
.success(function (result) {
$scope.datas = result;
})
.error(function (err) {
...
});
I explained fastly but i hope this is enough
Iv been trying to create an angularJS component for constructing a dynamic html table from a provided array.
The components template includes some ng-transclude directives as 'placeholders'/slots for templates provided by the component consumer.
Is it possible to transclude a <tr> template (with nested <th>), to be used inside the table <thead>?
I have tried using all variations for transclution:
transclude: true, transclude: 'element'
and transclude: { header: 'header'}
(the third option seems as the most suitable, as I will eventually required multiple elements to be transcluded).
Component:
app.component("virtualTable", {
bindings: {
someArray: "<"
},
transclude: {
header: "header"
},
templateUrl: () => {
return "/app/components/virtual-table.component.html";
});
Component Template:
<div>
<table>
<thead>
<tr ng-transclude="header"></tr>
</thead>
<tbody>
<tr ng-repeat="item in vt.someArray">
...another place for transclution...
</tr>
</tbody>
</table>
</div>
Consuming HTML (component declaration):
<virtual-table some-array="vm.personList">
<header>
<th>First Column</th>
<th>Second Column<th>
</header>
</virtual-table>
I excpect the compiled DOM to look like this:
<table>
<thead>
<tr>
<th>First Column</th>
<th>Second Column</th>
</tr>
</thead>
...
But instead I get the innerHTML of the transcluded element (header) as Text:
<table>
<thead>
<tr ng-transclude="header">
<header class="ng-scope">
First Column
Second Column
</tr>
</header>
...
I Suspect the browser (chrome 76) to somehow strip the <tr> tags from the transcluded element before it is being provided to the component (as it illegal us to use <tr> outside of a <table>).
I would like to maintain an html table structure.
Is The Any Way to Solve This?
I have a template like this, and I want ro make the table vertical(using partials is not an option in my environment, and I don't want to do it with inverted condition or duplicating html elements)
<table>
<tr>
<td>row1</td>
<td>row1</td>
<td>row1</td>
<tr>
</table>
The result should be:
<table>
<tr>
<td>row1</td>
</tr>
<tr>
<td>row1</td>
</tr>
<tr>
<td>row1</td>
<tr>
</table>
I already tried
var data = {
foo:true
}
<table>
<tr>
<td>row1</td>
{{#foo}}</tr><tr> {{/foo}}
<td>row1</td>
{{#foo}}</tr><tr> {{/foo}}
<td>row1</td>
<tr>
</table>
and
var data = {
foo:'</tr><tr>'
}
<table>
<tr>
<td>row1</td>
{{{foo}}}
<td>row1</td>
{{{foo}}}
<td>row1</td>
<tr>
</table>
A common misconception about Ractive is that because it uses the Mustache syntax, people think it acts like Mustache.
Mustache does string interpolation, where it replaces {{ }} to values that correspond in an object, and you get HTML. Ractive, on the otherhand, compiles the template into an AST. Then it uses that tree to create the DOM. It is similar to how Babel converts JSX into its object representation before feeding it to React, or how an HTML parser parses HTML, then constructing the DOM.
So for your scenario to work, you'll have to think in terms of properly-formed HTML:
Ractive.DEBUG = false;
const VerticalTableComponent = Ractive.extend({
template: `
<table border="1">
{{#tableItems}}
<tr>
<td>{{.}}</td>
</tr>
{{/}}
</table>
`
});
const app = VerticalTableComponent ({
el: '#app',
data: {
tableItems: ['foo', 'bar', 'baz', 'quz']
}
});
<script src="https://unpkg.com/ractive#0.8.12/ractive.min.js"></script>
<div id="app"></div>
I am working on an accounts page that lists transactions (credits and debits).
I would like the user to be able to click on a table row and it expands showing more information.
I am using Twitter bootstrap and have looked over the documentation and this is the result I have
<table class="table table-striped" id="account-table">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Description</th>
<th>Credit</th>
<th>Debit</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr data-toggle="collapse" data-target="#demo1" data-parent="#account-table" class="">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
<div id="demo1" class="demo out collapse">Demo1</div>
</tr>
See:
http://jsfiddle.net/2Dj7Y/
The only issue is that it displays the "dropdown information" in the wrong place, I would like to add in a new row, instead of printing it at the top of the table
I have also tried adding in a new table row (which just displays the row, and no collapse action (only applied to the first row)
<tr data-toggle="collapse" data-target="#demo1" data-parent="#account-table" >
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
<tr id="demo1" class="demo out collapse">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
</tr>
</tr>
See http://jsfiddle.net/ypuEj/
I'm not sure you have gotten past this yet, but I had to work on something very similar today and I got your fiddle working like you are asking, basically what I did was make another table row under it, and then used the accordion control. I tried using just collapse but could not get it working and saw an example somewhere on SO that used accordion.
Here's your updated fiddle:
http://jsfiddle.net/whytheday/2Dj7Y/11/
Since I need to post code here is what each collapsible "section" should look like ->
<tr data-toggle="collapse" data-target="#demo1" class="accordion-toggle">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
</tr>
<tr>
<td colspan="6" class="hiddenRow">
<div class="accordion-body collapse" id="demo1">Demo1</div>
</td>
</tr>
Expanding on Tony's answer, and also answering Dhaval Ptl's question, to get the true accordion effect and only allow one row to be expanded at a time, an event handler for show.bs.collapse can be added like so:
$('.collapse').on('show.bs.collapse', function () {
$('.collapse.in').collapse('hide');
});
I modified his example to do this here: http://jsfiddle.net/QLfMU/116/
If you're using Angular's ng-repeat to populate the table hackel's jquery snippet will not work by placing it in the document load event. You'll need to run the snippet after angular has finished rendering the table.
To trigger an event after ng-repeat has rendered try this directive:
var app = angular.module('myapp', [])
.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
Complete example in angular:
http://jsfiddle.net/ADukg/6880/
I got the directive from here:
Use AngularJS just for routing purposes
All the other answers address previous versions of Bootstrap. To implement this in the latest version -- Bootstrap 5 -- check out this link.