How to apply a class to a specific label in a row based on truthy value - vuejs3

I'm new to Vue 3. I have a table with rows. See screenshot below. Each row has a checkbox and a label in it. All I want to do is upon initial loading of the page view, have the correct class apply to the label depending on whether the child.status of that row is true-thy or not. Child status true is present. False = absent. Problem: when I initially load the page view all the labels are green regardless whether the child.status false or true.
Currently the Vue 3 code I have got so far works great, except for initial load. If I check the checkbox, I get the data I need and the label gets its green background. If I uncheck a checkbox, the green class disappears. Check it again and the green background reappears - Great. All's well except for initial page load where all the labels are green.
To help you understand I included a screenshot. You will notice behind each label there is a 1 or 0 to indicate whether it is truthy are not. You will see that even the false ones are green.
<template>
<div class="container">
<h5 class="heading ml-4">Children Absent / Present</h5>
<div class="border_charts">
<table class="table ">
<thead>
<tr class="col-4">
<th class="tableHeading col-4">First Name</th>
<th class="tableHeading col-4">Last Name</th>
<th class="tableHeading col-4 ">Absent / Present</th>
</tr>
</thead>
<tbody>
<tr v-for="child in Children" :key="child.child_id">
<td class="col-4"><a :href="'/getchild/'+ child.child_id">{{child.childFirstName}}</a></td>
<td class="col-4"> {{child.childLastName}}</td>
<td class="col-4">
<div class="form-check form-switch" >
<input
type="checkbox"
class="form-check-input"
role="switch"
:id="child.child_id"
v-model="child.status"
:true-value="1"
:false-value="0"
#change="updateChild(child)"
>
<label
class="form-check-label"
v-bind:for="child.child_id "
:class="{present:child.status}"
:true-value="1"
:false-value="0"
> {{ child.status ? absentPresent : absentPresent }}
</label>
{{child.status}}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
props: {
Children:{
Children:Array
},
},
data() {
return {
active:false,
inputClass: 'present',
absentPresent:'Absent/Present'
}
},
methods:{
updateChild(child){
this.changedChild = child;
console.log( this.changedChild);
this.inputClass = 'present'
this.active = ! this.active
},
},
}
</script>
<style scoped>
.present{
background-color: #5ba17a;
border-radius:0.25rem;
width:auto;
color:white;
text-align: center;
margin: 2px;
padding: 0px 5px 0px 5px;
}
.absent{
width:auto;
color:darkblue;
text-align: center;}
</style>

My guess is that child.status is initially loaded as string, so it is '0' instead of 0, and as with any non-empty string, Boolean('0') is true.
Check if you need to convert the values to numbers after loading, or if you can change the data source to send you numbers instead of strings.

Related

How to show a table on hovering a button in react?

I tried
class MyColorPicker extends React.Component {
render() {
const darkColors = ['#B80000', '#DB3E00', '#FCCB00', '#008B02', '#006B76', '#1273DE', '#004DCF', '#5300EB'];
const lightColors = ['#EB9694', '#FAD0C3', '#FEF3BD', '#C1E1C5', '#BEDADC', '#C4DEF6', '#BED3F3', '#D4C4FB'];
return (<div>
<button id="color">Select color</button>
<div className="picker">Text</div>
<div className="picker">
<table>
<tbody>
<tr>
{darkColors.map(color =>
<td style={{backgroundColor: color, width: 20, height: 20}} key={color}>{" "}</td>)}
</tr>
<tr>
{lightColors.map(color =>
<td style={{backgroundColor: color, width: 20, height: 20}} key={color}>{" "}</td>)}
</tr>
</tbody>
</table>
</div>
</div>);
}
}
css
.picker{
display: none;
}
#color:hover + .picker{
display: block !important;
}
The table does not show. I also tried adding a className to GithubPicker from react-color. Didn't work.
I don't want to set a state on hover because I have many components where I want to attach a button and a color picker. In this case, on hovering one button, all the other color pickers will show. I just want one color picker to show. How can I achieve this?
#color:hover + .picker work for element with class .picker just after #color:hover. In your case you have two .picker element. So first .picker will shown but as css second element will not show.
Please wrap both .picker div into a one div and put .picker class on wrapped div element.
Still you will get one more issue. As css you are trying to put hover css for button. When your mouse will move to picker, button hover will clear and again .picker will disappear.
So we have to wrap all element in one div and put hover css for wrapped div.
JSX
<div>
<div className="picker">
<button id="color">Select color</button>
<div className="picker-colors">
<div>Text</div>
<div>
<table>
<tbody>
<tr>
{darkColors.map(color => (
<td
style={{
backgroundColor: color,
width: 20,
height: 20
}}
key={color}
>
{" "}
</td>
))}
</tr>
<tr>
{lightColors.map(color => (
<td
style={{
backgroundColor: color,
width: 20,
height: 20
}}
key={color}
>
{" "}
</td>
))}
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
CSS
.picker-colors {
display: none;
}
.picker:hover .picker-colors {
display: block;
}
Here's a working example https://codesandbox.io/s/9yrr9wx60r

Hide checkbox using css

I have the code, which I get it from inspecting:
<td class=ox-list-pair style>
<input type="CHECKBOX" name="ox_CkSurvey_Sport__xava_selected" value="selected:0" onclick="openxava.onSelectElement('CkSurvey','Sport','null','row=0,viewObject=xava_view',this.checked,'ox_CkSurvey_Sport__0',false,'','border-bottom: 1px solid;','',false,false,0,'xava_tab')">
</td>
I have tried to hide the checkbox but none of them success.
My attempts:
input[type=checkbox].ox_CkSurvey_Sport__xava_selected {
display: none;
}
ox_CkSurvey_Sport__xava_selected {
display: none;
}
.ox_CkSurvey_Sport__xava_selected input[type="checkbox"]{
display:none;
}
Please note that <td> is valid as it is inside <tr> as well as <table>.
Please help me. Thanks.
You should read up on CSS selectors.
https://www.w3schools.com/cssref/css_selectors.asp
You are trying to hide the check box with the class "ox_CkSurvey_Sport__xava_selected", but that doesn't exist.
You need to do this:
input[type=checkbox][name=ox_CkSurvey_Sport__xava_selected] {
display: none;
}
Is your <td> valid? What makes a <td> valid is:
It must be in a <tr>
That <tr> must be in a <table>
Technically <tr> must be in a <tbody>, <thead>, or <tfoot> but the browser will create a <tbody> by default if there's a <table>.
In the demo there's:
a <table>, <tr>, <td>, and your messy checkbox.
a <td> and a simple checkbox.
Note: The selector is td.ox-list-pair > input[type="checkbox"] and it successfully hides the messy checkbox and fails to hide the simple checkbox. So as you can see that the browser will ignore an invalid <td> and everything within it. I'm going out on a limb and assume that your <td> is not inside a <tr> and/or <table>.
Demo
$('td.ox-list-pair > input[type="checkbox"]').css('display', 'none');
b {
color: red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td class='ox-list-pair' style>
<input type="CHECKBOX" name="ox_CkSurvey_Sport__xava_selected" value="selected:0" onclick="openxava.onSelectElement('CkSurvey','Sport','null','row=0,viewObject=xava_view',this.checked,'ox_CkSurvey_Sport__0',false,'','border-bottom: 1px solid;','',false,false,0,'xava_tab')">I'm
in a valid cell
</td>
</tr>
</table>
<td class='ox-list-pair'>
<input type="CHECKBOX">I'm in an <b>invalid</b> cell
</td>

How to easily add/remove cells from a Table (Shifting existent cells)

I want a table to automatically align cells to be two per row, meaning that if a add/remove a cell, cells will shift to be two per row (with one on last row if total number of cells is odd).
Example:
<table>
<tr>
<td>old1</td> <td>old2</td>
</tr>
<tr>
<td>old3</td> <td>old4</td>
</tr>
</table>
To this:
<table>
<tr>
<td>NEW</td> <td>old1</td>
</tr>
<tr>
<td>old2</td> <td>old3</td>
</tr>
<tr>
<td>old4</td>
</tr>
</table>
Notice the automatically added row.
I'll show you three ways to accomplish what you need,
css3 Using flex (modern browsers only)
css Using inline-table (problem with cell height but usable as sort-of fallback)
jquery Using standard <table> (All browsers!)
Using CSS3's FLEX
.table{
display: flex;
flex-wrap: wrap;
}
.cell{
width:50%;
background:#ddd;
}
<div class="table">
<div class="cell">NEW</div>
<div class="cell">OLD1</div>
<div class="cell">OLD2</div>
<div class="cell">OLD3<br>new line</div>
<div class="cell">OLD4</div>
</div>
Using inline-table (issue with cell height)
display: table;   for the parent element and
display: inline-table for the inner DIVs:
.table{
display:table;
}
.cell{
display:inline-table;
width:50%; /* With percentage you simulate "how-many-per-Row" */
background:#ddd;
}
<div class="table">
<div class="cell">NEW</div>
<div class="cell">OLD1</div>
<div class="cell">OLD2</div> <!-- Works but notice this cell height -->
<div class="cell">OLD3<br>new line</div>
<div class="cell">OLD4</div>
</div>
You could use the inline-table as a fallback for older browsers - it's not the exact same result but without JavaScript it's the best you could get.
Take a look in the specs about the display property: https://developer.mozilla.org/en-US/docs/Web/CSS/display
Using <table>, <tr> and <td> and JavaScript (jQuery)
If you want to stick to good 'ol table elements you can use "a bit" of jQuery.
In that case it's a bit more complicated (see code-comments):
jQuery(function($){ // DOM is now ready
var $table = $("table"); // Get your table
var maxRowCells = 2; // only 2-per-Row
var counter = 0; // just a dummy counter
function prependNewCell(){
var $newCell = $("<td/>", {html: "NEW"+(++counter)});
// Is the last row full?
if($table.find("tr:last td").length == maxRowCells){
// If true, append a new TR to TABLE to shift TD's to
$table.append( $("<tr/>") );
}
// Shift all last TD's to the next row:
$table.find("tr:not(:last)").each(function(){
var $tdLast = $(this).find("td").last();
$(this).next("tr").prepend( $tdLast );
});
// Finally. Prepend the new TD element to the first TR
$table.find("tr").first().prepend( $newCell );
}
$("button").on("click", prependNewCell);
});
td{
width:50%;
background:#ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>ADD NEW CELL ON TOP</button>
<table>
<tr>
<td>OLD1</td>
<td>OLD2</td>
</tr>
<tr>
<td>OLD3</td>
<td>OLD4</td>
</tr>
</table>
table {
empty-cells: hide;
}

Conditional ng-class style applies to all divs

I have a list of card numbers for a patient that displays on a modal. If the card is set to be the default card then it should have a grey background - this is based on a value of true for the object.
<td ng-repeat="obj in paymentAndShipping">
<div ng-click="setDefaultPaymentMethod(obj.ElectronicPaymentAccountType, obj.ElectronicPaymentAccountID)" ng-class="{'chosencard' : obj.PreferredAccount }">
<span ng-show="obj.PreferredAccount" class="glyphicon glyphicon-ok"></span>
<p>{{obj.ElectronicPaymentAccountType}} {{trimCardNum(obj.CreditCardNumber)}}</p>
<p>Exp: {{obj.ExpirationDate}}</p>
</div>
</td>
Important piece:
ng-class="{'chosencard' : obj.PreferredAccount }"
Relevant CSS:
.chosencard {
background-color: #gray-lighter;
}
Here you can see that I iterate over the array and retrieve the objects using an ng-repeat and then apply an ng-class on the div inside the table cell to determine if the style is applied. The odd thing is that I do the same exact thing on the span inside the div and it reacts as I expect but the actual div doesn't - why is that?
Here's a screenshot of the behaviour.
P.S. When I click on an individual div the grey background disppears from all the others except the div that I clicked on. And of the four objects that you see above only one of them has a value of true and that's the last card.
I can't see how you selecting payment methods but you can do that like in demo below.
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.paymentAndShipping = [
{
ElectronicPaymentAccountType: "a",
CreditCardNumber: "155652",
ExpirationDate: "01/01/2014",
ElectronicPaymentAccountID: 1
}, {
ElectronicPaymentAccountType: "b",
CreditCardNumber: "155652",
ExpirationDate: "01/11/2014",
ElectronicPaymentAccountID: 2
}, {
ElectronicPaymentAccountType: "c",
CreditCardNumber: "1545652",
ExpirationDate: "21/01/2414",
ElectronicPaymentAccountID: 3
}, {
ElectronicPaymentAccountType: "d",
CreditCardNumber: "1554652",
ExpirationDate: "31/01/2024",
ElectronicPaymentAccountID: 4
}
];
$scope.PreferredAccount = $scope.paymentAndShipping[0];
$scope.setDefaultPaymentMethod = function(index) {
$scope.PreferredAccount = $scope.paymentAndShipping[index];
}
});
.chosencard {
background-color: yellow;
}
td {
border:solid 1px grey
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<table>
<tr>
<td ng-repeat="obj in paymentAndShipping">
<div ng-click="setDefaultPaymentMethod($index)" ng-class="{'chosencard' :PreferredAccount==obj }">
<span ng-show="obj.PreferredAccount" class="glyphicon glyphicon-ok"></span>
<p>{{obj.ElectronicPaymentAccountType}} {{obj.CreditCardNumber}}</p>
<p>Exp: {{obj.ExpirationDate}}</p>
</div>
</td>
</tr>
</table>
<h3>PreferredAccount :</h3> {{PreferredAccount | json }}
</div>
</div>

How to get the kendo NumericalTextBox to share the width of a table cell the same way the kendo DropDownList does?

I have a very simple form laid our in a table with one row and two cells. I have a kendo NumericalTextBox in one cell and a Text Input in the other. I have the table width set to 100% and no width on the cells.
The Problem:
The problem is that the NumericalTextBox takes up more that 50% width in it's cell, and squashes up the Text Input.
I have tested this with a kendo DropDownList and it works fine. It just takes 50%.
Why is the NumericalTextBox pushing out it's cell to more than 50% and how can I stop it doing this?
I realize I can put a style="width:50%" on the table cells, but this is an overhead on larger forms, as if you add a cell you have to go and update all your other cells width percentages etc...
Ideally I just want to be able to say the width of the table is 100% and the cells will equally share that, and each control in each cell will take up 100% of the cell width.
I put together a demo page that shows what is going on:
HTML:
<div id="testContainer">
<strong>Numerical TextBox and DropDownList</strong>
<table class="mistro-form">
<tr>
<td>
<label>Numerical TextBox:</label>
<input data-role="numerictextbox"
data-format="n0"
data-min="0"
data-decimals="0" />
</td>
<td>
<label>Drop Down List:</label>
<select name="Include Title"
data-role="dropdownlist"
data-value-primitive="true">
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</td>
</tr>
<table>
<div style="height:20px"></div>
<strong>Drop Down List and Text Input</strong>
<table class="mistro-form">
<tr>
<td>
<label>Drop Down List:</label>
<select name="Include Title"
data-role="dropdownlist"
data-value-primitive="true">
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</td>
<td>
<label>Include Title:</label>
<input type="text" class="form-control" />
</td>
</tr>
<table>
</div>
CSS:
table.mistro-form {
width:100%;
}
.mistro-form td {
padding: 5px;
vertical-align: top !important;
}
.mistro-form .k-dropdown, .mistro-form .k-combobox, .mistro-form .k-numerictextbox, .mistro-form .k-textbox, .mistro-form .k-numerictextbox {
width: 100% !important;
}
JavaScript:
$(document).ready(function() {
kendo.init($('#testContainer'));
});
Here is a fiddle of the above code: http://jsfiddle.net/codeowl/UQdGQ/6/
Thank you for your time,
Regards,
Scott
Ok I just worked this out. I just needed to set the table-layout css property to fixed;
eg;
table.mistro-form {
width:100%;
table-layout:fixed;
}
Hope this can save someone else some time ;-)

Resources