How to change background color of a cell based on condition in ngx-datatable? - angular2-template

I am using ngx-datatable. I want to change background color of any
particular cell based on value/condition. I am unable to change
background color for any particular cell. Whatever i am trying its
changing for entire column.
CSS:
.my-custom-cell-notSet {
background-color: red;
}
.my-custom-cell-yes {
background-color: rgb(51, 255, 102);
}
.my-custom-cell-no {
background-color: yellow;
}
TS:
rows2 = [
{
sno: "2.1",
answers: "Not set",
}, {
sno: "2.2",
answers: "Not set",
}
];
setColorChange(val,RowIndex)
{
this.tableColumnListIndex3 = RowIndex;
this.colorstatus= true;
if (val === 'Not Set' ) {
this.mycolor2 = 'my-custom-cell-notSet';
} else if (val === 'No' ) {
this.mycolor2 = 'my-custom-cell-yes';
} else if (val === 'Yes') {
this.mycolor2 = 'my-custom-cell-no';
} }
HTML:
<ngx-datatable class="material striped ngx-datatable fixed-header
fullscreen" [rows]="rows2" [columnMode]="'force'" [headerHeight]="50"
[footerHeight]="100" [rowHeight]="'auto'">
<ngx-datatable-column
name="S.NO">
<ng-template let-column="column" ngx-datatable-header-template>{{column.name | titleCase}} </ng-template>
<ng-template let-row="row" let-rowIndex="rowIndex" ngx-datatable-cell-template>{{row.sno}}</ng-template>
</ngx-datatable-column>
<ngx-datatable-column *ngIf="colorstatus==true && mycolor2=='my-custom-cell-notSet'"
name="Answer (y/n)" [cellClass]="mycolor2">
<ng-template let-column="column" ngx-datatable-header-template>
{{column.name | titleCase}}</ng-template>
<ng-template let-row="row" let-rowIndex="rowIndex" ngx-
datatable-cell-template>
<span [hidden]="tableColumnListIndex3==rowIndex&& tableIndex3">
{{(tableColumnListIndex3 == rowIndex && tableIndex3) ? row.answers : row.answers}}
</span><select class="form-control" [(ngModel)]="row.answers"
name="answer3" *ngIf="tableColumnListIndex3==rowIndex && tableIndex3"
class="rowInputs"
(Change)="setColorChange2(row.answers,rowIndex)">
<option
value='Not Set' translate>Not Set
</option>
<option value='Yes' translate>Yes
</option>
<option value='No' translate>No</option>
</select></ng-template>
</ngx-datatable-column>
</ngx-datatable>

I think you need ng-class for this: there is a nice example in the documentation:
link

Related

Unable to login to PayPal account from PayPal button

I have a paypal Smart Button on my WordPress site:
https://baranovich.org/pay-for-auction-purchase/
The code is from PayPal and I edited it a little because the input fields were not displaying properly.
When I use the button, everything seems fine, but then I can't pay by logging into another account.
It just doesn't log in. It doesn't give me an error either.
After I enter the email it goes back to here but I haven't logged in...
I tied clearing the cache, and used different browsers and PCs.
I checked out the answer https://stackoverflow.com/questions/53840252/unable-to-login-to-paypal-using-paypal-payment-button-localhost
But I don't understand why I'm even using the sandbox PayPal feature. I wanted a real button, not a sandbox test button...
How do I put a real PayPal button?
Here is the code I am using:
<style>
input {
border-top-style: hidden;
border-right-style: hidden;
border-left-style: hidden;
border-bottom-style: groove;
background-color: #eee;
}
</style>
<div id="smart-button-container">
<div style="text-align: center">
<label for="description">First and Last Name </label>
<span style="display:inline-block; width:10px;"></span>
<input type="text" name="descriptionInput" id="description" maxlength="127" value=""></div>
<p id="descriptionError" style="visibility: hidden; color:red; text-align: center;">Please enter a First and Last Name</p>
<div style="text-align: center"><label for="amount">Amount to Pay </label>
<span style="display:inline-block; width:10px;"></span>
<input name="amountInput" type="number" id="amount" value="" ><span> USD</span></div>
<p id="priceLabelError" style="visibility: hidden; color:red; text-align: center;">Please enter the full amount owed</p>
<div id="invoiceidDiv" style="text-align: center; display: none;"><label for="invoiceid">Auction Lot Number </label>
<span style="display:inline-block; width:10px;"></span>
<input name="invoiceid" maxlength="127" type="text" id="invoiceid" value="" ></div>
<p id="invoiceidError" style="visibility: hidden; color:red; text-align: center;">Please enter the Lot number</p>
<div style="text-align: center; margin-top: 0.625rem;" id="paypal-button-container"></div>
</div>
<script src="https://www.paypal.com/sdk/js?client-id=sb&enable-funding=venmo&currency=USD" data-sdk-integration-source="button-factory"></script>
<script>
function initPayPalButton() {
var description = document.querySelector('#smart-button-container #description');
var amount = document.querySelector('#smart-button-container #amount');
var descriptionError = document.querySelector('#smart-button-container #descriptionError');
var priceError = document.querySelector('#smart-button-container #priceLabelError');
var invoiceid = document.querySelector('#smart-button-container #invoiceid');
var invoiceidError = document.querySelector('#smart-button-container #invoiceidError');
var invoiceidDiv = document.querySelector('#smart-button-container #invoiceidDiv');
var elArr = [description, amount];
if (invoiceidDiv.firstChild.innerHTML.length > 1) {
invoiceidDiv.style.display = "block";
}
var purchase_units = [];
purchase_units[0] = {};
purchase_units[0].amount = {};
function validate(event) {
return event.value.length > 0;
}
paypal.Buttons({
style: {
color: 'gold',
shape: 'pill',
label: 'paypal',
layout: 'horizontal',
},
onInit: function (data, actions) {
actions.disable();
if(invoiceidDiv.style.display === "block") {
elArr.push(invoiceid);
}
elArr.forEach(function (item) {
item.addEventListener('keyup', function (event) {
var result = elArr.every(validate);
if (result) {
actions.enable();
} else {
actions.disable();
}
});
});
},
onClick: function () {
if (description.value.length < 1) {
descriptionError.style.visibility = "visible";
} else {
descriptionError.style.visibility = "hidden";
}
if (amount.value.length < 1) {
priceError.style.visibility = "visible";
} else {
priceError.style.visibility = "hidden";
}
if (invoiceid.value.length < 1 && invoiceidDiv.style.display === "block") {
invoiceidError.style.visibility = "visible";
} else {
invoiceidError.style.visibility = "hidden";
}
purchase_units[0].description = description.value;
purchase_units[0].amount.value = amount.value;
if(invoiceid.value !== '') {
purchase_units[0].invoice_id = invoiceid.value;
}
},
createOrder: function (data, actions) {
return actions.order.create({
purchase_units: purchase_units,
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (orderData) {
// Full available details
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
// Show a success message within this page, e.g.
const element = document.getElementById('paypal-button-container');
element.innerHTML = '';
element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
},
onError: function (err) {
console.log(err);
}
}).render('#paypal-button-container');
}
initPayPalButton();
</script>
Sandbox buttons can only be logged into with a sandbox payer account from the developer dashboard.
Since you want a live button, you'll need to regenerate it when logged into your live PayPal account that you want to receive the payments. Alternatively, manually change the code that says client-id=sb to use a live client ID from a live REST App, which are created in the developer dashboard -> My Apps & Credentials.

Why is nuxt-link refreshing the page when used with Bootstrap-vue?

I am using nuxt and bootstrap to build a custom hover dropdown menu for navigation. The issue I have is that my navigation submenu NuxtLinks are refreshing the entire page instead of smoothly changing the app content in my Nuxt block. The nav bar is dynamically generated in the default.vue layout and uses a b-dropdown-hover component where the NuxtLink is wrapped around that content. Why does the page do a full refresh for those links/anchors but my b-navbar-brand image does a smooth transition? I apologize, I am very new to Nuxt. This video # ~1:35:00 demonstrates what I'm trying to do.
components/BDropdownHoverRight.vue
<template>
<nuxt-link :to="aTo">
<div class="ddr-top" #mouseover="onOver1($event.target)" #mouseleave="onLeave1($event.target)">
<b-dropdown ref="dropdown_ddr" :text="cText" class="m-md-2 ddr">
<slot></slot>
</b-dropdown>
</div>
</nuxt-link>
</template>
<script>
export default {
name: 'BDropdownHoverRight',
props: {
cText: {
type: String,
},
aTo: {
type: String,
},
},
methods: {
onOver1(t) {
if (t.nodeName === 'DIV') {
console.log(t)
console.log(t.nodeName)
let num_child_nodes = 0
try {
if (t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length >= 0) {
num_child_nodes = t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length
}
} catch (e) {
if (t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length >= 0) {
num_child_nodes = t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length
}
}
if (num_child_nodes > 0) {
try {
t.querySelectorAll(':scope > div > ul')[0].style.display = 'block'
} catch (e) {
try {
t.querySelectorAll(':scope > ul')[0].style.display = 'block'
} catch (e) {}
}
}
}
},
onLeave1(t) {
try {
t.querySelectorAll(':scope > div > ul')[0].style.display = 'none'
} catch (e) {
try {
t.querySelectorAll(':scope > ul')[0].style.display = 'none'
} catch (e) {}
}
},
},
}
</script>
layouts/default.vue
<template>
<div>
<b-navbar id="top-nav-bar" toggleable="lg" type="light" sticky>
<b-navbar-brand to="/">
<Rabbit id="tl-logo" />
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<template v-for="dir in navtop_dd">
<b-dropdown-hover
:key="dir.id"
:c-text="dir.name"
:a-to="dir.hasOwnProperty('ato') ? dir.ato : '/nolink'"
>
<template v-if="'submenus' in dir && dir.submenus.length > 0">
<template v-for="dir1 in dir.submenus">
<b-dropdown-hover-right
:key="dir1.id"
:c-text="dir1.name"
:a-to="dir1.hasOwnProperty('ato') ? dir1.ato : '/nolink'"
>
<template v-if="'submenus' in dir1 && dir1.submenus.length > 0">
<template v-for="dir2 in dir1.submenus">
<b-dropdown-hover-right
:key="dir2.id"
:c-text="dir2.name"
:a-to="dir2.hasOwnProperty('ato') ? dir2.ato : '/nolink'"
>
</b-dropdown-hover-right>
</template>
</template>
</b-dropdown-hover-right>
</template>
</template>
</b-dropdown-hover>
</template>
</b-navbar-nav>
<!-- Right aligned nav items -->
<b-navbar-nav class="ml-auto">
<b-nav-form>
<b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input>
<b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button>
</b-nav-form>
<b-nav-item-dropdown right>
<!-- Using 'button-content' slot -->
<template #button-content>
<b-img src="../assets/imgs/account-circle.svg" style="height: 35px"> </b-img>
<!-- <em>User</em> -->
</template>
<b-dropdown-item href="#">Profile</b-dropdown-item>
<b-dropdown-item href="#">Sign Out</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<b-container id="app-content">
<Nuxt />
</b-container>
<div id="footer">
<div style="height: 100%; padding: 5px">© 2021</div>
</div>
</div>
</template>
<script>
import BDropdownHover from '#/components/BDropdownHover'
import BDropdownHoverRight from '#/components/BDropdownHoverRight'
export default {
components: {
BDropdownHover,
BDropdownHoverRight,
},
data() {
return {
navtop_dd: [
{
id: 1,
name: 'Transactions',
ato: '/transactions',
submenus: [
{
id: '1a',
name: 'Sales Orders',
ato: '/transactions/salesorders',
submenus: [
{
id: '1b',
name: 'New',
},
{
id: '2b',
name: 'List',
},
],
},
{
id: '2a',
name: 'Item Fulfillments',
ato: '/transactions/itemfulfillments',
submenus: [
{
id: '1b',
name: 'New',
},
{
id: '2b',
name: 'List',
},
],
},
],
},
{
id: 2,
name: 'Inventory',
},
{
id: 3,
name: 'Reports',
},
{
id: 4,
name: 'Setup',
},
{
id: 5,
name: 'Support',
},
],
}
},
mounted() {
var x = document.querySelectorAll('.b-dropdown.navtop-dd')
for (var i = 0; i < x.length; i++) {
if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) {
var btn = x[i].querySelectorAll(':scope > .btn')[0]
btn.classList += ' no-content-after'
}
}
var x = document.querySelectorAll('.b-dropdown.ddr')
for (var i = 0; i < x.length; i++) {
if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) {
var btn = x[i].querySelectorAll(':scope > .btn')[0]
btn.classList += ' no-content-after'
}
}
},
}
</script>
<style>
#top-nav-bar {
border-bottom: 1px solid green;
}
#tl-logo {
height: 40px;
margin: 5px;
}
#footer {
height: 40px;
color: black;
border-top: 1px solid green;
margin: auto;
text-align: center;
display: flex;
align-items: center;
justify-content: space-around;
}
.navtop-dd button {
background: none !important;
color: #6c757d !important;
border: none !important;
}
#app-content {
margin: 20px auto;
}
.ddr > button::after {
display: inline-block;
margin-left: 0.555em;
right: 0px;
content: "";
border-top: 0.25em solid transparent;
border-right: 0.3em solid transparent;
border-bottom: 0.25em solid transparent;
border-left: 0.35em solid;
vertical-align: 0.075em;
}
.b-dropdown {
width: 100%;
}
.ddr > button {
text-align: left;
}
.no-content-after::after {
content: none !important;
}
.ddr > ul {
top: -1.2rem;
left: calc(100% - 0.5rem);
}
.dropdown-menu {
min-width: 0 !important;
}
.dropdown-item {
color: #6C757D;
}
.ddr-top:hover {
background-color: #e4ffda;
}
a:hover {
text-decoration: none !important;
}
</style>
There is a LOT of irrelevant code here. I took the time to format it properly. Please make the effort yourself next time (to format and input interesting bits only).
Also, the answer on how to fix the issue was actually given in the video itself. The video is talking about the differences between a and nuxt-link tags.
Which relates to this part of Bootstrap's Vue documentation where you can see that
[to] prop: Denotes the target route of the link. When clicked, the value of the to prop will be passed to router.push() internally, so the value can be either a string or a Location descriptor object
So, you should use something like this
<template>
<b-dropdown>
<template #button-content>
Custom <strong>Content</strong> with <em>HTML</em> via Slot
</template>
<b-dropdown-item to="/test">Go to test page via Vue-router</b-dropdown-item>
</b-dropdown>
</template>
I also saw that your code is rather different from the video. You should not use querySelector, you don't have to import Nuxt components neither and you have several ESlint warning/errors.
I do recommend trying to focus on a single part of learning and not mixing all of them. It's fine to want to go a bit further, but be careful of not being lost with too much abstraction while you do learn a lot of new concepts (Vue/Nuxt).
On a side note, if you want to continue learning Nuxt, you can check this: https://masteringnuxt.com/ (created by a Nuxt ambassador and other well known people in the Vue ecosystem)
Have fun creating projects with Nuxt!

Detect radio input getting unchecked (by clicking another radio input) in Vue

I want to give my label a border when the radio input is selected but I can only detect when the radio input is being activated. I know it's possible to do this in CSS with some tricks but I want to do it through Javascript.
<fieldset>
<label>
<input type="radio" name="test" #change="someMethod">
test
</label>
<label>
<input type="radio" name="test" #change="someMethod">
test
</label>
</fieldset>
methods: {
someMethod () {
console.log('something')
}
}
I was hoping to call the someMethod method when the input state would change between checked and unchcked, but this change is only called when the input is clicked (checked).
https://jsfiddle.net/alucardu/qhbpg2yj/1/
Use $refs to check all the radio inputs and use an array to store the previous state, then we can manage to do it:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
previous_refs:[],
},
methods:{
someMethod(){
for(const key in this.$refs){
if(this.previous_refs[key]!==undefined &&
this.previous_refs[key].checked===true &&
this.$refs[key].checked===false){
console.log(this.$refs[key].id+' un-checked, do something');
}
if(this.$refs[key].checked===true){
console.log(this.$refs[key].id+' checked, do something');
}
if(this.previous_refs[key]===undefined){
this.previous_refs[key]={checked:this.$refs[key].checked};
}
else{
this.previous_refs[key].checked=this.$refs[key].checked;
}
}
},
}
})
Please check https://jsfiddle.net/sLw4e0p8/92/ to see details.
Managed to do it through CSS: https://jsfiddle.net/alucardu/qhbpg2yj/7/
Trick was adding a before to the checked input:
label {
display: flex;
position: relative;
input:checked {
&::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border: 1px solid blue;
}
}
}

Subcomponent value binded to the property of another instance of the same vue component

I have an issue with a custom component. Here's the problem:
This screen is actually 3 times the same Vue component:
<div class="passwords__form">
<InputField class="passwords__field" label="Mot de passe actuel" :password="true" v-model="currentPassword" />
<InputField class="passwords__field" label="Nouveau mot de passe" :password="true" v-model="newPassword" />
<InputField class="passwords__field" label="Répéter le nouveau mot de passe" :password="true" v-model="repeatedPassword" />
<Button title="Changer le mot de passe" #click="updatePassword"/>
</div>
Here's the component code:
<template>
<div
class="field__container"
:class="{ 'field__container--disabled': disabled }"
>
<label
:for="this._uid"
class="field__label"
:class="{ 'field__label--disabled': disabled }"
v-if="labelEnabled"
>{{ label }}</label
>
<input
:id="this._uid"
class="field__input"
:class="{
'left-rounded': !labelEnabled && !password,
'right-rounded': !buttonEnabled && !password
}"
:value="value"
:placeholder="placeholder"
#input="$emit('input', $event.target.value)"
#keyup.enter="$emit('keyup-enter')"
:disabled="disabled"
:type="fieldType"
/>
<input
v-if="password && enableShowPassword"
type="checkbox"
v-model="showPassword"
id="password-checkbox"
class="field__password-checkbox"
/><label
v-if="password && enableShowPassword"
for="password-checkbox"
class="field__password-checkbox-label"
:class="{
'right-rounded': !buttonEnabled,
}"
><span v-if="enableShowPassword && showPassword"><EyeSlash class="field__password-checkbox-icon"/></span><span v-if="!showPassword" ><Eye class="field__password-checkbox-icon field__password-checkbox-icon--eye " /></span></label>
<a
v-if="buttonEnabled"
class="field__button"
#click.stop="$emit('button-click')"
>
{{ button }}
</a>
</div>
</template>
<script lang="ts">
import Component from "vue-class-component";
import Vue from "vue";
import { Prop } from "vue-property-decorator";
import Eye from "../assets/images/icons/eye-regular.svg"
import EyeSlash from "../assets/images/icons/eye-slash-regular.svg"
#Component({
components: {
Eye,
EyeSlash
}
})
export default class InputField extends Vue {
#Prop({ default: "", required: false })
label!: string;
#Prop({ required: true })
value!: string;
#Prop({ default: "", required: false })
placeholder!: string;
#Prop({ default: "", required: false })
button!: string;
#Prop({ default: false, required: false })
disabled!: boolean;
#Prop({ default: false, required: false })
password!: boolean;
#Prop({ default: true, required: false })
enableShowPassword!: boolean;
showPassword = false;
get fieldType(): string {
if (this.password && !this.showPassword) {
return "password";
}
return "text";
}
get labelEnabled(): boolean {
return this.label !== "";
}
get buttonEnabled(): boolean {
return this.button !== "";
}
}
</script>
<style lang="scss">
.field {
&__container {
display: flex;
flex-direction: row;
border: 1px solid $color-grey-7;
font-size: 1.6rem;
transition: all 0.3s;
&:hover:not(&--disabled),
&:focus:not(&--disabled) {
border: 1px solid $color-complementary;
& > .field__label {
background: $color-complementary;
}
}
&--disabled {
cursor: not-allowed;
}
}
&__label {
text-align: center;
padding: 0.5rem 2rem;
border-right: 1px solid $color-grey-8;
background-color: $color-grey-8;
transition: all 0.3s;
&--disabled {
cursor: not-allowed;
}
}
&__input {
flex-grow: 2;
border: none;
color: $color-grey-1;
transition: all 0.3s;
padding: 0 1rem;
&:hover,
&:focus {
outline: none;
}
&--disabled {
cursor: not-allowed;
}
}
&__button {
text-align: center;
padding: 0.5rem 2rem;
border-left: 1px solid $color-grey-7;
transition: all 0.3s;
&:hover,
&:active {
background: $color-grey-7;
}
}
&__password-checkbox {
display: none;
}
&__password-checkbox-label {
background-color: $color-grey-9;
padding: 0.6rem 1rem;
cursor: pointer;
&:hover,
&:active {
background-color: $color-complementary-lighter;
}
}
&__password-checkbox-icon {
width: 1.5rem;
&--eye {
position: relative;
top: 1px;
}
}
}
</style>
I think the problem come from the v-model property on the checkbox. From what I see, the v-model binds to the showPassword property of the first instance of InputField, instead of binding to the current instance of InputField.
I'm not sure why it behaves like that and what my error is, and how to correct it/do it the right way. Does someone have any leads ?
I suppose you should use an unique id for an input type="password" as you did for an usual input :id="this._uid" because on a HTML page all id's declared in elements must be unique.

Dynamically add styles from array Vue

I have some progress bar the width of which are getting from data from the array. The color of this bar depends on the same data. There are 3 colors if progress is 0 the color is grey, more than 0 its blue, and if it 100 its should be green.
<div class="card-item" v-for="item in status" :key="item.id"> // loop
<div class="progress-item">
<span>{{item.progress}}%</span> // data from arr
<div class="progress-bar">
<div class="progress-bar-inner" :style="{width: item.progress}"></div> // width in style should in %
</div>
</div>
</div>
Maybe i should to write the function?
You can use a method or inline the logic in a style object.
If you only have 3 cases, I would use a conditional class instead of styles, though.
Here's a codepen that shows many possibilities: https://codepen.io/Flamenco/pen/gjNxXp?editors=1111
methods: {
theColor(item){
return item.length===0 ? 'grey' : item.length < 100 ? 'blue' : 'green'}
}
}
<div>using inline style</div>
<div :style="{color: item.length===0 ? 'grey' : item.length < 100 ? 'blue' : 'green'}">...</div>
<div>using method</div>
<div :style="{color: theColor(item)}">...</div>
Using conditional class. Much easier to read, debug, maintain, and extend.
methods: {
theClass(item) {
if (item.length === 0) return 'none'
else if (item.length < 100) return 'under'
else return 'over'
}
}
.none {
color: grey;
}
.under {
color: blue;
}
.over {
color: green;
}
<div>A few ways to do this...</div>
<div :class='theClass(item)'>...</div>
<div :class='[theClass(item), "anotherClass"]'>...</div>
<div :class='{[theClass(item)]:true, anotherClass:true]}'>...</div>