Meteor ReactLink integration - meteor

I am interested in two way binding.
How can I use Meteor-React with ReactLink ?
I tried this package:
https://github.com/victoransel/meteor-react-linkedstate-mixin
But when I include both the meteor and reactlink mixin, I get an error :
linkState is not a function
Thanks

Add React.addons.LinkedStateMixin to your component mixins:
YourComponent = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState(){
return {
test: ""
}
}
});
This should allow you to link state like this within your render method:
<input type="text" valueLink={this.linkState('test')} />

Related

Is there a way to use a prop as the site-key for vue-recaptcha?

I have a Form component in Vue where I import the vue-recaptcha like this:
<template>
... Contains the form and button that triggers onSubmit function
</template>
<script>
import { VueReCaptcha } from 'vue-recaptcha-v3';
Vue.use(VueReCaptcha, {
siteKey: "hard-coded site-key here",
loaderOptions: {
useRecaptchaNet: true,
},
});
export default {
methods: {
async onSubmit(e) {
// Uses the recapatcha and handles errors/success etc.
},
},
};
...
This works since the value for site-key is hard-coded.
However, I wish to be able to pass the site-key as a prop to the Form component and then use this as the site-key.
I tried something as bold as simply creating a prop in the Form component and passing it in as the site-key when setting the vue-recaptcha options, like this:
<script>
import { VueReCaptcha } from 'vue-recaptcha-v3';
Vue.use(VueReCaptcha, {
siteKey: this.siteKey,
loaderOptions: {
useRecaptchaNet: true,
},
});
export default {
props: {
siteKey: String,
},
...
</script>
This does not work because this.siteKey is undefined, as expected. However, is there a way to set the site-key value as the prop siteKey? Maybe there is a way to set the vue-recaptcha plugin options inside the component where this.siteKey isn't undefined, for example in mounted()?
Have you tried to provide the Key to the Form over prop?
<my-form siteKey="<My Site Key>" ...
or
<my-form site-key="<My Site Key>" ...
Pay attention:
You should be careful with components and prop's naming & using, since there are DOM
Template Parsing Caveats

Vue 3 with Tailwind using v-bind:class shows classes in html element but not render while style works correctly

I am new to Vue and I'm trying to bind multiple classes in a v-for loop from a const array of object imported from a file.js.
But the trick I'm trying is to import const and than return classes from method that evaluates one property of object looped.
I've tried all ways, methods, computed, setup, onMounted, beforeMount, but even if i can see my classes in html they aren't rendered in styles section of DevTools.
The only way that works is to v-bind:style instead of class. Or just put exact classes in my const array object as a property but I prefer to avoid this.
It seems to save something in cache, but i have tried to delete and to lunch application in hidden mode but it won't works
Is there someone who can help me to understand and maybe to resolve?
Thanks in advance
this is my actual code:
<template>
<div id="cv" class="tp3-flex md:tp3-grid md:tp3-grid-cols-[repeat(27,_minmax(0,_1fr))] md:tp3-grid-rows-[repeat(6,_minmax(0, 5rem))] tp3-justify-center tp3-content-center tp3-justify-items-center tp3-mx-auto tp3-p-2 tp3-bg-cyan-500 tp3-text-blue-50">
<div v-for="(softSkill, index) in softSkills" :key="`softSkill-${index}`"
class="tp3-flex tp3-w-20 tp3-h-20 -tp3-rotate-45 tp3-rounded-full tp3-rounded-tr-none tp3-justify-center tp3-items-center tp3-bg-slate-400 tp3-opacity-70 tp3-mb-4 tp3-mt-4 tp3-shadow-md tp3-overflow-hidden"
v-bind:class="posCols(softSkill)">
<div class="tp3-rotate-45">
<span v-html="softSkill.text"></span>
</div>
</div>
</div>
</template>
<script>
import {softSkills} from "#/assets/skills/softSkills";
export default {
name: "ComponentSoftSkills",
data(){
return{
softSkills: null
}
},
beforeMount() {
this.softSkills = softSkills;
},
methods: {
posCols(softSkill){
console.log(softSkill);
return ' tp3-col-start-['+softSkill.col+'] tp3-col-end-['+(softSkill.col+1)+']';
}
}
}
</script>
<style lang="css" scoped>
</style>
and my file.js is:
export const softSkills = [
{text:`skill 1`, col:1, row:1},
{text:`skill 2`, col:5, row:1},
{text:`skill 3`, col:2, row:2},
{text:`skill 4`, col:15, row:1},
]
I have a suspicion that this might be due to your tailwind setup.
Because the classes are assigned dynamically and tailwind (depending on the configuration) is only making classes available that it can find during compilation. So the classes, even though you see them populated correctly, are not made available through tailwind. simply put, when tailwind scans the code, it doesn't recognize md:tp3-grid-cols-[repeat(27,_minmax(0,_1fr))] or tp3-col-start-[${softSkill.col}] as a valid class name and does not generate the class for it.
Assuming this is the issue and not knowing the exact version on configuration can't give an exact solution, but here are some tips for it.
Instead of using dynamic class names, define all the class names and assign dynamically
so instead of using tp3-col-start-[${softSkill.col}] tp3-col-end-[${(softSkill.col+1)}]
you could make sure all possible classes are clear and accessible by the tailwind parser:
let colClass = `tp3-col-start-[0] tp3-col-end-[1]`;
if(softSkill.col === 1) colClass = "tp3-col-start-[1] tp3-col-end-[2]";
if(softSkill.col === 2) colClass = "tp3-col-start-[2] tp3-col-end-[3]";
if(softSkill.col === 3) colClass = "tp3-col-start-[3] tp3-col-end-[4]";
if(softSkill.col === 4) colClass = "tp3-col-start-[4] tp3-col-end-[5]";
if(softSkill.col === 5) colClass = "tp3-col-start-[5] tp3-col-end-[6]";
// ...etc
this is obviously very verbose, but the classes are clearly defined in the code, so tailwind can find them when scanning your code.
Safelisting classes
using safelisting of classes is another option. Instead of having the code in your js, you would have it in the configuration
// tailwind.config.js
module.exports = {
// ...other stuff
safelist: [
'tp3-col-start-[0]',
'tp3-col-start-[1]',
'tp3-col-start-[2]',
'tp3-col-start-[3]',
'tp3-col-start-[4]',
'tp3-col-start-[5]',
// ...etc
'tp3-col-end-[1]',
'tp3-col-end-[2]',
'tp3-col-end-[3]',
'tp3-col-end-[4]',
'tp3-col-end-[5]',
// ...etc
],
}
there's also a way to use regex, which might look something like this:
// tailwind.config.js
module.exports = {
// ...other stuff
safelist: [
{
pattern: /tp3-col-start-[(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15)]/,
variants: ['sm', 'lg'], // you can add variants too
},
{
pattern: /tp3-col-end-[(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16)]/,
},
],
}
you can read more about safelisting here safelisting-classes

How can get custom tags inside web component

I'm new in webcomponents with stenciljs, I'm testing creating a select, the idea with this code create and render the select:
<rhx-select label-text="A select web component">
<rhx-select-item value="1" text="option 1"/>
<rhx-select-item value="2" text="option 2"/>
</rhx-select>
The problem i have is how can i get the tags that inside my web component?
this is my code:
import { Component, h, Prop, } from '#stencil/core';
#Component({
tag: 'rhx-select',
styleUrl: 'select.css',
shadow: true,
})
export class RhxSelect {
#Prop() labelText: string = 'select-rhx';
#Prop() id: string;
#Element() el: HTMLElement;
renderOptions() {
let data = Array.from(this.el.querySelectorAll('rhx-select-item'));
return data.map((e) =>{
<option value={e.attributes.getNamedItem('value').value}>{e.attributes.getNamedItem('text').value}</option>
});
}
render(){
return (
<div>
<label htmlFor={this.id}>
{this.labelText}
</label>
<select id={this.id} class="rhx-select">
{this.renderOptions()}
</select>
</div>
)
}
}
Thank you for your time.
If you add the #Element() decorator you can parse the children with vanilla JS:
getItems() {
return Array.from(this.el.querySelectorAll('rhx-select-item'));
}
You can then use those elements and their properties/attributes however you want, for example to generate a list of <option> elements.
A good example is ion-select which gets the children in the childOpts() getter function.
A couple things to keep in mind:
You'll probably want to hide the items with display: none
If the options might change after the initial load you'll need to listen for those changes. Ionic uses the watchForOptions function.
this.el.querySelectorAll won't return any elements until after the component has rendered once, so that its children are available in the DOM. Therefore you will have to use something like the componentDidLoad hook:
export class RhxSelect {
// ...
#State()
items: HTMLRhxSelectItemElement[] = [];
componentDidLoad() {
this.items = Array.from(this.el.querySelectorAll('rhx-select-item'));
}
render() {
return (
<div>
<label htmlFor={this.id}>
{this.labelText}
</label>
<select id={this.id} class="rhx-select">
{this.items.map(item => (
<option value={item.getAttribute('value')}>{item.getAttribute('text')}</option>
))}
</select>
</div>
)
}
}
Note however that componentDidLoad is only executed once, after the component has loaded. If you want your component to support dynamic changes to the options, then you'll have to use something else, like componentDidRender, but then you'll also have to make sure you don't end up with an infinite render loop. There's also a couple ways to solve this, by combining different lifecycle methods.
See https://stenciljs.com/docs/component-lifecycle for a list of all available lifecycle methods.

How to select a template conditionally with Ractive

I'm trying to select a template conditionally. My idea was that I'd be able to have a container (view) with a list of components, where each component would state which template it should use.
{{#view.components}}
{{> {{template.id}} }}
{{/view.components}}
What I'd like to happen is for the partial declaration to resolve {{template.id}} from the component property called id, then resolve the partial.
i.e.
view.components[0].template.id = "fooTemplate" (<script id="fooTemplate" />)
view.components[1].template.id = "barTemplate" (<script id="barTemplate" />)
and ractive to resolve the #view.components block as
{{>fooTemplate}}
{{>barTemplate}}
This {{>template.id}}, tells me it can't resolve template.id.
This {{>{{template.id}} }} tells me it doesn't know anything about t.
Any workaround I could use?
Take a look to the docs: http://docs.ractivejs.org/latest/partials in "Injecting partials".
You could do something like this in the partials:
ractive = new Ractive({
el: myContainer,
template: myTemplate,
partials: {
content: anyBooleanExpression ? fooTemplate: barTemplate,
}
});
You can use the same conditional in the template property:
template: anyBooleanExpression ? fooTemplate: barTemplate,
And even to use more complex conditionals adding a swich block or an anonymous function.
template: function(){ /* you complex logic */ },
Like in this fiddle
You can define your template as below:
{{#view.components}}
{{#FooTemp}}
{{>fooTemplate}}
{{/FooTemp}}
{{#BarTemp}}
{{>barTemplate}}
{{/BarTemp}}
{{/view.components}}
and your model is like:
{
view: {
components: [
{
FooTemp: { ... }
},
{
BarTemp: { ... }
}
]
}
}

Meteor Flow Router React: I am passing a component as a prop, and I want to include a prop in that component

See this code:
authenticatedRoutes.route( '/study/:studyId/study_settings', {
name: 'study_settings',
action(params, queryParams) {
console.log(queryParams);
Session.set('studyId', params.studyId);
mount( Default, { yield: <PageContainer pageName='Study Settings' page={<StudySettings />}/> } );
}
});
As you can see the page prop? in the mount function? I am passing <StudySettings /> component
well I want to pass a prop into this component
but when I try <StudySettings queryPage=queryParams.subPage /> I get compile error.
How can I do this?
When you want to pass a prop to a ReactJS Component that is a variable you need to use {} so in your case you need to do something like this
<StudySettings queryPage={ queryParams.subPage } />
Let me know if you have anyother questions!

Resources