ng-if in ng-repeat angularjs - javascript

I need to define different style by the value of a champ in ng-repeat, i try this :
<thead>
<tr><th>#</th><th>Nom</th><th>Ville</th><th style="width: 50%;">Lignée</th></tr>
</thead>
<tbody>
<tr ng-repeat="alternate1 in alternateViewText1.features | orderBy:'fiche.id*1'">
<td>{{alternate1.fiche.id}}</td>
<td ng-if="alternate1.properties.statut_activite == 'yes'" style="color: green;">{{alternate1.properties.nom}}</td>
<td ng-if="alternate1.properties.statut_activite == 'no'" style="color: red;">{{alternate1.properties.nom}}</td>
<td>{{alternate1.properties.ville}}</td>
<td>{{alternate1.properties.lignee}}</td>
</tr>
</tbody>
it's not working (nothing show)
how can i define automatically a style with a particular value ?

You can create a class for particular style and use ng-class like this :
JS FIDDLE
css:
.green
{
color:green;
}
.red
{
color:red;
}
html:
<td data-ng-class="{'green' : alternate1.properties.statut_activite == 'actif', 'red': alternate1.properties.statut_activite == 'inactif'}">{{alternate1.properties.nom}}</td>

You use the wrong value in your test
jsFiddle
Replace yes by actif and no by inactif
Example :
<td ng-if="alternate1.properties.statut_activite == 'actif'" style="color: green;">{{alternate1.properties.nom}}</td>
<td ng-if="alternate1.properties.statut_activite == 'inactif'" style="color: red;">{{alternate1.properties.nom}}</td>
PS:
The answer of ssilas777 is the best way to execute this switch of css class

Related

How do I expand and collapse (i.e. toggling) a table row (tr)?

With my preexisting knowledge (for example this one) I have seen so far that a div container can easily be toggled (i.e. hide and show). However I am pretty confused when I have some data inside tr and I want to display and hide few items once that tr is clicked. Let's consider a food menu (I name it "Rice"), and there are few sub menus under that category (I name them "Fried rice", "Boiled rice"...). Once the "Rice" is clicked (or possibly if I have a arrow or plus icon to click on), the sub menus should get displayed. Similarly, they should hide themselves once the arrow is clicked again.
Please see in this website how they toggle the restaurant menu with arrow key. I want to do the exactly same thing.
The code I am working on:
<div class="media-right">
<table class="table">
<tr>
<td>
<h3 class="menu-title">Rice</h3>
</td> <!--make this tr expandable and collapsable-->
<td>
<div class="menu-rate">$100.00</div>
</td>
</tr>
<tr>
<td>
<h3 class="menu-title">Fried Rice</h3></td>
<td>
<div class="menu-rate">$50.00</div>
</td>
</tr>
<tr>
<td>
<h3 class="menu-title">Boiled Rice</h3></td>
<td>
<div class="menu-rate">$25.00</div>
</td>
</tr>
</table>
</div>
You can try a class "Accordion" which has the similar functionality.
You can find it here in detail.
<script>
$(function(){
$('.menu-rate').click(function(){
$(this).closest('.container').toggleClass('collapsed');
});
});
</script>
Something like this?
function Rice(){
if(document.getElementById("Rice").style.display == "none"){
document.getElementById("Rice").style.display = "block";
}else{
document.getElementById("Rice").style.display = "none";
}
}
function boiledRice(){
if(document.getElementById("boiledRice").style.display == "none"){
document.getElementById("boiledRice").style.display = "block";
}else{
document.getElementById("boiledRice").style.display = "none";
}
}
function friedRice(){
if(document.getElementById("friedRice").style.display == "none"){
document.getElementById("friedRice").style.display = "block";
}else{
document.getElementById("friedRice").style.display = "none";
}
}
<div class="media-right">
<table class="table">
<tr>
<td>
<a onclick="Rice()"><h3 class="menu-title">Rice</h3></a><div id="Rice" style="display:none;"><ul><li>1</li><li>2</li><li>3</li></ul></div></td> <!--make this tr expandable and collapsable-->
<td>
<div class="menu-rate">$100.00</div>
</td>
</tr>
<tr>
<td>
<a onclick="friedRice()"><h3 class="menu-title">Fried Rice</h3></a><div id="friedRice" style="display:none;"><ul><li>1</li><li>2</li><li>3</li></ul></div></td>
<td>
<div class="menu-rate">$50.00</div>
</td>
</tr>
<tr>
<td>
<a onclick="boiledRice()"><h3 class="menu-title">Boiled Rice</h3></a><div id="boiledRice" style="display:none;"><ul><li>1</li><li>2</li><li>3</li></ul></div></td>
<td>
<div class="menu-rate">$25.00</div>
</td>
</tr>
</table>
</div>
Is there a constraint that is forcing you to utilize a table? Since you're already using jQuery, you could easily achieve this type of functionality with jQuery UI's accordion widget.
$( "#accordion" ).accordion({
collapsible: true
});
Here's a basic example.
If you're open to use a library for this, you can try using bootstrap-table by wenzhichin. I find it very flexible.
Subtable - http://issues.wenzhixin.net.cn/bootstrap-table/#options/sub-table.html
Collapsing row - http://issues.wenzhixin.net.cn/bootstrap-table/#methods/expandRow-collapseRow.html
checkout collapsible elements on material design made by google, really helpful an easy to use:
http://materializecss.com/collapsible.html

Run jQuery function in Angular App

I'm using jquery in an html table, this is my first example FIDDLE
the thing is when I try to pass this example to my angular app it doesnt work
This is my view in agular:
<table class="table table condensed drillDown">
<thead>
<tr style="background-color: #E3E3E3">
<th style="width: 5%"></th>
<th style="text-align: center">Categories</th>
<th style="text-align: center">LW $</th>
<th style="text-align: center">LW</th>
<th style="text-align: center">L4 W</th>
<th style="text-align: center">L13 W</th>
<th style="text-align: center">L52 W</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="d in category" class="parent">
<td ng-class="expand" style="cursor: pointer"></td>
<td>{{d.desc}}</td>
<td>{{d.LW$}}</td>
<td>{{d.LW}}</td>
<td>{{d.L4W}}</td>
<td>{{d.L13W}}</td>
<td>{{d.L52W}}</td>
</tr>
<tr ng-repeat="d in subcat" class="child">
<td ng-class="expand" style="cursor: pointer"></td>
<td>{{d.desc}}</td>
<td>{{d.LW$}}</td>
<td>{{d.LW}}</td>
<td>{{d.L4W}}</td>
<td>{{d.L13W}}</td>
<td>{{d.L52W}}</td>
</tr>
</tbody>
</table>
So as you can see, I call my parent, child and expand class the same way I'm doing on the regular html example but I cant make it work
The jquery code that im using is in the fiddle, but I read that this can be done by using a directive but I dont know how to do this, Im new with angular.
Some help would be nice
This is my example using angular Angular FIDDLE example
Yes, a directive would be the way to go. I created an example using your jQuery in a directive here:
https://jsfiddle.net/h90Luy3h/
The directive is restricted to the drill-down attribute in the td tag. I'm a fan of using attributes or elements over classes for directive hooks because I think they're easier to identify and you can be pretty explicit with what it's doing by the name of the directive. Classes as hooks can get messy and really should only apply to a style rather than a dom identifier, but that's definitely a personal preference.
function drillDown() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope,element) {
var table = $('.categories-table');
table.each(function() {
var $table = $(this);
$table.find('.parent').each(function(){
if($(this).nextUntil('.parent', ".child").length > 0){
$(this).children('td:first').html('+');
}
});
$table.find('.child').each(function(){
if($(this).nextUntil('.child', ".grandson").length > 0){
$(this).children('td:first').html('+');
}
});
var $childRows = $table.find('tbody tr').not('.parent').hide();
$table.find('button.hide').click(function() {
$childRows.hide();
});
});
element.on('click',function(){
if($(this).parent().hasClass('parent') == true)
{
console.log("----Parent");
if ($(this).text() == "+")
$(this).text("-")
else
$(this).text("+");
$(this).parent().nextUntil('.parent', ".child").fadeToggle("slow", "linear");
$(this).parent().nextUntil('.parent', ".grandson").hide("fast");
$(this).parent().nextUntil('.parent', ".child").each(function(){
if($(this).children('td:first').text() == '-')
$(this).children('td:first').text('+');
});
}
else if($(this).parent().hasClass('child') == true)
{
console.log("----Child");
if ($(this).text() == "+")
$(this).text("-")
else
$(this).text("+");
$(this).parent().nextUntil('.child', ".grandson").fadeToggle("slow", "linear");
}
});
}
}
The table in the angular version doesn't exist when your jQuery function is trying to run, so the jQuery function isn't able to modify the table.
Angular is really a different way of building UIs, so it would be useful to read up about directives and the angular lifecycle. A super useful discussion on the topic: "Thinking in AngularJS" if I have a jQuery background?
I don't have much of an answer, but you need more than just a code snippet here.

Table expand & collapse not working in angular js

Below is the tabular structure for expand & collapse, i have done using table. Now i have used the below script for collapse & expand. But sometime i succeeded in expand & sometime don't.
What i did, when i got response from the api, i call this function :
$timeout(function (){
$scope.initExpandCollapse();
},1000);
$scope.initExpandCollapse = function () {
angular.element(document).on("click", ".table_exp", function(){
var TBODY = angular.element(this).parents(3);
if(TBODY.hasClass("open")){
TBODY.children("tr.expand-table-row").hide();
TBODY.removeClass("open");
return false;
}
TBODY.addClass("open");
TBODY.children("tr.expand-table-row").show();
});
}
If you guys, can help me out for this problem . Thanks.
CSS:
tr.expand-table-row {
display: none;
}
tr.expand-table-row.open {
display: initial;
}
Angular
$scope.expandCollapse = function expandCollapse (item) {
item.open = !item.open
}
HTML
<table>
<tbody>
<tr ng-repeat="item in items track by $index"">
<td ng-click="expandCollapse(item)">++++</td>
<td>
<table>
<tr ng-class="{'open': item.open}" class="expand-table-row open">
<td>{{item.name}}</td>
<td ng-repeat="data in item.options">{{data.name}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
You need nested tables so the click marker does not simply vanish with the rest, apart from that the salient point is the ng-class="{'open': item.open}" espression that sets the class open if the property open on item is set.
Try to use window.onload instead of $timeout, or add you script to the end of body tag.

Displaying link conditionally in Angular.js

Basically, I have this code in my template:
<tr ng-repeat="entry in tableEntries">
<td ng-switch="entry.url == ''">
<span ng-switch-when="false">{{entry.school}}</span>
<span ng-switch-when="true">{{entry.school}}</span>
</td>
...
</tr>
As you can see I'm trying to display a clickable URL when entry.url is not empty and a plain text otherwise. It works fine, but it looks quite ugly. Is there a more elegant solution?
Another way I can think of doing it is using ng-if:
<td>
<span ng-if="entry.url != ''">{{entry.school}}</span>
<span ng-if="entry.url == ''">{{entry.school}}</span>
</td>
But then I would be repeating almost the same comparison twice, which looks even worse. How would you guys approach this?
You can try.
<div ng-show="!link">hello</div>
<div ng-show="!!link">hello</div>
But the ngSwitch which you are using should be fine.
Use double negation, it cast into boolean thus !!entry.url will return true if string is not empty.
<td ng-switch="!!entry.url">
<span ng-switch-when="true">{{entry.school}}</span>
<span ng-switch-when="false">{{entry.school}}</span>
</td>
A good read What is the !! (not not) operator in JavaScript? and Double negation (!!) in javascript - what is the purpose?
You can create a custom directive that hides the complexity:
HTML
<tr ng-repeat="entry in tableEntries">
<td>
<link model="entry"></link>
</td>
...
</tr>
JS
app.directive('link', function() {
return {
restrict: 'E',
scope: {
model: '='
},
template: '<a ng-if="model.url != ''" href="{{model.url}}">{{model.school}}</a><span ng-if="model.url == ''"> {{ model.school }}</span>'
}
});
I would recommend having an ng-class="{'className': whenEntryURLisWhatever}" in your td, and make it change the css styles accessed, e.g:
td span{ /*#normal styles#*/ }
.className span{ /*#styles in the case of added classname (when it is a link)#*/
text-decoration: underline;
cursor: pointer;
}
Then just change what happens on ng-click within a function defined in your javascript code.
$scope.yourFunction = function(url){
if(!!url){
window.location = YourURL;
}
}
This would cut down on code repetition, as your html could now be:
<tr ng-repeat="entry in tableEntries">
<td ng-class="{'className': !!entry.url}">
<span ng-click="yourFunction(entry.url)">{{entry.school}}</span>
</td>
...
</tr>

onmouseout not triggering but onmouseover is

Here is a simplified fiddle
I have a table with sub-groupings inside of it. I want these sub-groupings to be hidden until the user clicks the sub-header row, which looks like this:
<tr class="title" name="titleGroup"
onmouseover='this.innerHTML=this.innerHTML.replace("---","+++");'
onmouseout='this.innerHTML=this.innerHTML.replace("+++","---");'
onclick="$('.Group').toggle();">
<td colspan="2">--- Group ---</td>
</tr>
So, onmouseover, should change the row to look like: +++ Group +++
and onmouseout should change it back to: --- Group ---
However, only the onmouseover triggers and I cannot get the text to go back.
I initially had the mouse over/out calling a function, but that has the same result. Also note that this page is dynamically generated so the text is not always "Group".
What am I doing wrong and how can I get onmouseout to reset the text?
Maybe you wanted to use onmouseleave event? :)
The proper use of replace function in your case and onmouseleave event:
<table width="550px">
<tr class="title" name="titleGroup" >
<td
onmouseover='this.innerHTML=this.innerHTML.replace(/-{3}/g,"+");'
onmouseleave='this.innerHTML=this.innerHTML.replace(/\+{3}/g,"-");'
onclick="$('.Group').toggle();"
colspan="2">--- Group ---</td>
</tr>
<tr class="Group" style="display:none;">
<td>
<b>Group</b>
HCS:</td>
<td>
<input type="checkbox" name="did4" />
</td>
</tr>
<tr class="Group" style="display:none;">
<td>
<b>Group</b>
NCD:</td>
<td>
<input type="checkbox" checked="" name="did5" />
</td>
</tr>
</table>
ANOTHER EDIT:
Firefox doesn't support onmouseleave event on TR marks! Move those events deffinition to
<td>
Building off of adeneo's fiddle, using jQuery with mouseleave is the way to go. However, the text could include a - or + so I had to update a bit to specifically look for 3 in a row.
Here is the final jQuery:
$('.title').on('mouseenter mouseleave', function(e) {
$('td', this).text(function(_,txt) {
return txt.replace(/[+]{3}|[-]{3}/g, function(x) {
return x=='---' ? '+++' : '---';
});
});
});
http://jsfiddle.net/jQRR7/29/
Checkout http://jsfiddle.net/jQRR7/30/
This works (at least in webkit browsers, Firefox still to be done)
onmouseover='this.innerHTML=this.innerHTML.replace(/-/g,"+");'
onmouseleave='this.innerHTML=this.innerHTML.replace(/\+/g,"-");'
It contains 2 issues:
a) replace() will replace only 1x, unless you hand over a regular expression (attention: do not surround the regex by quotes!) More about replace() can be found at http://devdocs.io/javascript/global_objects/string/replace DevDocs.io JS replace()
b) mouse over seems to be called, but mouseout just 1x,so only 1 time +++ will be replaced
Can you switch to CSS3 (pseudo elements like :after are supported by all major browser version) or do you need to stick on js?
take a look at http://jsfiddle.net/jQRR7/31/
HTML
<table>
<tr class="title" name="titleGroup" style="background: #c3c3c3" onclick="$('.Group').toggle();">
<td colspan="2">Group with CSS3</td>
</tr>
</table>
CSS
.title td {
font-weight: bold;
text-align: center;
cursor: pointer;
}
td:before{
content: '+++ ';
}
td:after{
content: ' +++';
}
tr:hover td:before{
content: '--- ';
}
tr:hover td:after{
content: ' ---';
}

Categories

Resources