How to apply onClick in the input - javascript

As you can this is a string js and I want to use onClick on the input whose view is being toggled by selecting the boolean value edit. Please suggest how to use onchnage here.
Already tried normal HTML onchange (not working)
onchange="${onchnage}"
Pls, suggest if you happen to know the answer.
export const DefaultNode = (d, selectedNodeIds, edit, fomatOptions, inputOnclick) => {
const mainData = d.data.data
return `<div style='background:${selectedNodeIds.length!==0 ? (selectedNodeIds.includes(d.data.id) ? `rgba(${ fomatOptions.nodeBg.r }, ${ fomatOptions.nodeBg.g }, ${ fomatOptions.nodeBg.b }, ${ fomatOptions.nodeBg.a })`: "#fff"): `rgba(${ fomatOptions.nodeBg.r }, ${ fomatOptions.nodeBg.g }, ${ fomatOptions.nodeBg.b }, ${ fomatOptions.nodeBg.a })`};
color:${selectedNodeIds.length!==0 ?(selectedNodeIds.includes(d.data.id) ?`rgba(${ fomatOptions.textColor.r }, ${ fomatOptions.textColor.g }, ${ fomatOptions.textColor.b }, ${ fomatOptions.textColor.a })`:'#000'): `rgba(${ fomatOptions.textColor.r }, ${ fomatOptions.textColor.g }, ${ fomatOptions.textColor.b }, ${ fomatOptions.textColor.a })`}'
class=${`"w-[250px] p-3 rounded-[15px] relative border-[3px] h-[140px] ${selectedNodeIds.includes(d.data.id)? 'drop-shadow-md' :"shadow"} ${ selectedNodeIds.includes(d.data.id) && fomatOptions.fontFamily.value}"`}>
<div class='flex justify-between w-full '>
<div class="">
${edit? `<input onclick='${inputOnclick}' class="fullName text-[13px] font-semibold" value="${mainData.name}"/>` : `<div class=" text-[13px] font-semibold">${mainData.name} </div>`}
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.position } </div>
<div class='mt-2'>
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.email } </div>
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.phone } </div>
</div>
</div>
<img class='w-10 h-10 mr-2 rounded-[10px]' src=${mainData.imgUrl} />
</div>
<div class='flex pt-4 justify-between items-center'>
<p class='text-[10px] font-medium uppercase bg-theme-gray px-2 text-black rounded-full py-0.5'>${mainData.department}</p>
<p class='text-[10px] font-medium uppercase mr-2'>${mainData.location}</p>
</div>
${((selectedNodeIds.includes(d.data.id))) ? `<div class="absolute left-4 -top-5 font-semibold text-[10px] p-1 bg-gray-400 text-white rounded-t-md">
Selected
</div>`: `<p></p>`}
</div>`
}

I believe what you're missing here is the different naming conventions for default HTML event listeners in React, not all of your code is here so I'm assuming you do not have a custom function called onchange, but in React its called onChange (or onClick, etc) so you're looking something like this for your code snippet.
onChange="${onchnage}"
Also double-check to make sure you have all your syntax and spelling correct. Also for writing better JSX for returning HTML elements you can write code like the following
return (
<div>
<p>Text here</p>
</div>
);

Related

interpolate javascript if statement into html

In a javascript file I currently have some HTML saved into a variable.
However I only want to display the middle section of the HTML on a condition. See the if code.length == 1.
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id=${this.id}><div> <h5 class="font-bold text-blue-700 text-sm mb-1 pr-2"> ${Name}</h5> <p class="text-sm text-blue-500"> if (Code.length == 1) { <span class="font-semibold mr-1"><%= t("common.code") %></span> <span> </span> } </p></div></div>`
However I can't seem to get this working. Is this possible?
That line is too long to be maintainable. Break it up so you can see what's going on.
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id=${this.id}><div> <h5 class="font-bold text-blue-700 text-sm mb-1 pr-2"> ${Name}</h5> <p class="text-sm text-blue-500">`;
if (Code.length == 1) {
html += `<span class="font-semibold mr-1"><%= t("common.code") %></span> <span> </span>`;
}
html += `</p></div></div>`
Use a variable
In your HTML snippet you are already using variables. Why not stick to that by making the content a variable. See snippet below with values added as an example using a variable content.
This part seems prepared server-side: <%= t("common.code") %>. You know how to do that yourself I'm assuming.
let Code = 'K';
let id = '5'; // this.id;
let Name = 'Herring';
var content = Code.length == 1 ? `<span class="font-semibold mr-1"><%= t("common.code") %></span>` : '';
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id="${id}"><div>
<h5 class="font-bold text-blue-700 text-sm mb-1 pr-2">${Name}</h5>
<p class="text-sm text-blue-500">${content}</p>
</div></div>`;
console.log(html);

Programmatically Set an href Link in React

I have a product that I want to programatically set a Checkout Session URL and then redirect a user when they click on an tag.
const PlanComponent = () => {
const [tiers, setTiers] = useState([]);
async function CheckoutSessionUrl(tierId) {
var result = null
await CreateCheckoutSession(
"PRODUCT_ID",
tierId,
"UID"
).then(function(response) {
result = response
})
return result;
};
async function LoadProducts() {
var result = []
await GetProducts("PRODUCT_ID").then(function(response) {
for (var i = 0; i < response.length; i++) {
var tier_id = response[i]["tier_id"]
CheckoutSessionUrl(tier_id).then(function(tier_response) {
response[i]["url"] = tier_response;
})
}
console.log("printing tiers");
console.log(response);
return response;
}).then(function(response){
result = response;
setTiers(result)
return result;
});
return result;
}
useEffect(() => {
// Some initialization logic here
LoadProducts().then(function(response) {
console.log("setting tiers")
console.log(response)
//setTiers(response)
})
}, []);
return (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:flex-col sm:align-center">
<h1 className="text-5xl font-extrabold text-gray-900 sm:text-center">Pricing Plans</h1>
<p className="mt-5 text-xl text-gray-500 sm:text-center">
Start building for free, then add a site plan to go live. Account plans unlock additional features.
</p>
</div>
<div className="mt-12 space-y-4 sm:mt-16 sm:space-y-0 sm:grid sm:grid-cols-2 sm:gap-6 lg:max-w-4xl lg:mx-auto xl:max-w-none xl:mx-0 xl:grid-cols-4">
{tiers.map((tier) => (
<div key={tier.name} className="border border-gray-200 rounded-lg shadow-sm divide-y divide-gray-200">
<div className="p-6">
<h2 className="text-lg leading-6 font-medium text-gray-900">{tier.name}</h2>
<p className="mt-4 text-sm text-gray-500">{tier.description}</p>
<p className="mt-8">
<span className="text-4xl font-extrabold text-gray-900">${tier.price}</span>{' '}
<span className="text-base font-medium text-gray-500">/mo</span>
</p>
<a
href={tier.url}
className="mt-8 block w-full bg-gray-800 border border-gray-800 rounded-md py-2 text-sm font-semibold text-white text-center hover:bg-gray-900"
>
Buy {tier.name}
</a>
</div>
<div className="pt-6 pb-8 px-6">
<h3 className="text-xs font-medium text-gray-900 tracking-wide uppercase">What's included</h3>
<ul role="list" className="mt-6 space-y-4">
{tier.users.map((feature) => (
<li key={feature} className="flex space-x-3">
{/*<CheckIcon className="flex-shrink-0 h-5 w-5 text-green-500" aria-hidden="true" />*/}
<span className="text-sm text-gray-500">{feature}</span>
</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
</div>
)
}
so if you look at the href={tier.url} it's not being set correctly. I feel like I'm not doing this correctly. Would love some feedback on how to actually get this working properly. IT looks like the tier.url new field isn't being set correctly (doesn't exist in the initial request but all the other attributes work).
The other option I wanted to do was when a user clicked a Button, it would generate a URL and redirect a user to that new external url but the navigation kept breaking.
Oh I found out what was happening. I needed to replace
await GetProducts("PRODUCT_ID").then(function(response) {
with
await GetProducts("PRODUCT_ID").then(async function(response) {

Change button based on click vuejs tailwind

I have expanded this code for my own learning abilities. I understand I can definitely shorten this down a LOT but I am trying to learn and expand my frontend experience.
So I have the code below. When localstorage it set to true/false it picks up the right v-if/else section. Now, what I need to do is set the local storage based on button click.
What is the best way to accomplish this?
<div v-if="privateChat == 'false'">
<button type="button">
<a key="privateChat" href="#" class="bg-red-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<ChatIcon class="h-6 w-6 text-white"/>
<span class="pt-2">Private Chat OFF</span>
</a>
</button>
</div>
<div v-else>
<button type="button">
<a key="privateChat" href="#" class="bg-green-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<ChatIcon class="h-6 w-6 text-white"/>
<span class="pt-2">Private Chat ON</span>
</a>
</button>
</div>
<script>
export default {
data() {
return {
privateChat: (localStorage.getItem("privateChat") === 'true') ? 'true' : 'false',
}
},
methods: {
clickPrivateChat (value) {
this.privateChat = value === true ? "true" : "false";
localStorage.setItem("privateChat", value);
},
setup() {
const enabled = ref(privateChat)
let value = localStorage.getItem("privateChat");
let privateChat = (value === 'true');
}
</script>
There are several improvements you can make...
use actual true/false values instead of "true", "false" strings
DRY: you just need one button; use a Vue computed value to show "ON" or "OFF"
use conditional :class logic to apply bg-green-900 class
script:
data() {
return {
privateChat: (localStorage.getItem("privateChat") === true) ? true : false,
}
},
computed: {
onOrOff() {
return this.privateChat ? 'ON' : 'OFF'
}
},
methods: {
clickPrivateChat (value) {
this.privateChat = !this.privateChat
localStorage.setItem("privateChat", value)
},
setup() {
const enabled = ref(privateChat)
let value = localStorage.getItem("privateChat")
let privateChat = (value === true)
}
},
markup:
<div>
<button type="button" #click="clickPrivateChat">
<a key="privateChat" href="#" :class="privateChat?'bg-green-900':''" class="bg-red-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<span class="pt-2">Private Chat {{ onOrOff }}</span>
</a>
</button>
</div>
improved Vue approach

Next.js - Expected server HTML to contain a matching <div> in <div>

Live example available here
I'm trying to make a basic layout where, on mobiles, only the latest posts appear. On desktop, the left column should be the posts and the right column the top categories and most popular posts.
Here is the layout:
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => {
const cols = useScreenType()
return cols === '2-cols' ? (
<div className="w-full flex justify-between items-start">
<ListPosts data-comp="ListPosts" className="w-4/6" />
<div className="sticky ml-12 w-2/6 flex flex-col">
<TopCategories data-comp="TopCategories" className="w-full" />
<PopularPosts data-comp="PopularPosts" className="mt-4" />
</div>
</div>
) : (
<ListPosts data-comp="ListPosts" className="w-full" />
)
}
Here's the useScreenType hook:
import { useMediaQuery } from 'react-responsive'
export const useScreenType = () => {
const is2Cols = useMediaQuery({ minWidth: 1300 })
const is1Cols = useMediaQuery({ minWidth: 800 })
if (is2Cols) {
return '2-cols'
}
if (is1Cols) {
return '1-cols'
}
return 'fullscreen'
}
And I keep getting this error:
Warning: Expected server HTML to contain a matching <div> in <div>.
div
ListPosts#webpack-internal:///./components/posts/ListPosts.tsx:31:19
div
IndexLayout#webpack-internal:///./components/layout/IndexLayout.tsx:28:149
div
Index#webpack-internal:///./pages/index.tsx:24:149
ApolloProvider#webpack-internal:///./node_modules/#apollo/client/react/context/ApolloProvider.js:13:18
s#webpack-internal:///./node_modules/next-apollo/dist/index.es.js:26:1911
div
div
MyApp#webpack-internal:///./pages/_app.tsx:37:19
ErrorBoundary#webpack-internal:///./node_modules/#next/react-dev-overlay/lib/internal/ErrorBoundary.js:23:47
ReactDevOverlay#webpack-internal:///./node_modules/#next/react-dev-overlay/lib/internal/ReactDevOverlay.js:73:20
Container#webpack-internal:///./node_modules/next/dist/client/index.js:155:20
AppContainer#webpack-internal:///./node_modules/next/dist/client/index.js:643:18
Root#webpack-internal:///./node_modules/next/dist/client/index.js:779:19
Now I think the issue is due to the useScreenType hook not being able to get a width because window isn't defined on the server. But how can I fix this issue? And not only do I get an error, but my HTML renders weirdly.
The final render ends up being something like this (when it renders as '2-cols'):
<div class="flex flex-col justify-start items-start w-full">
<div class="mt-6 w-full"></div>
<div class="mt-4 flex items-center cursor-pointer transform transition hover:scale-105 text-sm">
<div class="w-full p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div>
<div class="mt-4 p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div>
</div>
</div>
Note: I am using Next.js v10.2.0
Code can be found on GitHub
As you notice, you cant access window object on server, so if you want to server-render something based on window object - you must hardcode these values.
The only thing you can rely on is user-agent in request headers, which gives you some understanding of user device.
For example this way you can detect user device in _app.js:
const device = deviceDetector.detect(isServer() ? ctx.req.headers['user-agent'] : window.navigator.userAgent)
deviceDetector is any kind of device detection implementation based on user agent
For anyone wondering how I fixed this, I ditched the responsive design with logic and switched to CSS. Here is my layout post fix (changed some classes with the lg prefix [documentation]):
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => {
return (
<div className="mt-12 lg:mt-24 w-5/6 mx-auto flex items-start">
<div className="w-full flex justify-between items-start">
<ListPosts className="lg:w-4/6 w-full" />
<div className="hidden sticky ml-12 w-2/6 lg:flex flex-col">
<TopCategories className="w-full" />
<PopularPosts className="mt-4" />
</div>
</div>
</div>
)
}

Vue dynamic background image inline component

I'm building a banner with Vue that needs to have a dynamic background, however, it doesn't seem to be working. Not sure what I'm doing wrong. I've tried a few other ways and it works if I do an image tag something like
<img :src="require(`#/assets/images/${backgroundImage}`)" />
But obviously this needs to be an inline background image.
Code:
component
<template>
<div
class="w-full h-64 bg-auto bg-no-repeat bg-center lg:bg-cover relative"
:style="{ backgroundImage: url(require('#/assets/images/' + backgroundImage))}"
>
<div class="w-full h-full flex flex-col justify-center items-center text-white px-6">
<div class="hero-text rounded text-center py-8 px-12">
<p class="text-base lg:text-md uppercase font-medium">{{ smallLeadingText }}</p>
<h1 class="text-xl md:text-3xl lg:text-5xl uppercase font-bold">{{ mainText }}</h1>
<p class="text-base lg:text-md">{{ subText }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: "PageHero",
props: {
backgroundImage: String,
smallLeadingText: {
type: String,
required: false
},
mainText: {
type: String,
required: true
},
subText: {
type: String,
required: false
}
}
};
</script>
View
<PageHero
backgroundImage="mc-background.png "
smallLeadingText="Powerful, secure & affordable"
mainText="Minecraft hosting"
subText="Plans suitable for all budgets"
/>
Looks like you've just got some syntax errors in your style attribute around string quoting. Try
<div :style="{ backgroundImage: `url(${require('#/assets/images/' + backgroundImage)})` }">
Might be easier to create some computed properties to resolve everything though
computed: {
bgImage () {
return require('#/assets/images/' + this.backgroundImage)
},
inlineStyle () {
return {
backgroundImage: `url(${this.bgImage})`
}
}
}
and
<div :style="inlineStyle">
Demo ~ https://codesandbox.io/s/crimson-sky-ehn9r

Categories