How to use RXJs Subject like store variable in Svelte - rxjs

How to use RXJs Subject like store variable in Svelte? You can use the Subject variable in Svelte with $ prefix. But when you bind the variable to input it throws an exception: "Error: name.set is not a function" because the Subject type has not a set method.

You can use RxJs Subject like a store variable in Svelte as in the example below.
<script>
import {Subject} from "rxjs";
let name = new Subject();
setTimeout(()=>{name.next("text")}, 1000);
</script>
<h1>Hello {$name}!</h1>
But if you try to use the name variable with a bind directive it throws an exception: "Error: name.set is not a function".
<script>
import {Subject} from "rxjs";
let name = new Subject();
$: console.log($name);
</script>
<h1>Hello {$name}!</h1>
<input bind:value={$name} />
To solve this issue, you can add a set method to the Subject class with a simple trick :).
<script>
import {Subject} from "rxjs";
Subject.prototype.set = function (value) {
this.next(value);
}
let name = new Subject();
$name = "Ali";
$: console.log($name);
</script>
<h1>Hello {$name}!</h1>
<input bind:value={$name} />

Related

problems in using custom Hook

I am starting with react just learning to create Custom hooks,but having issue with while creating this custom hook to turn a sentence to sentence case.There is no error and also not showing the output(I want like "HeLLO WORld" to as "Hello world")Can't find out where I am making the mistake,kindly help me out.Here is the code
The custom hook-
import UsePascalCase from "../CustomHooks/UsePascalCase"
export default function TextBoxDemo(){
var text="";
function handleOnInputEntry(e){
text=e.target.value
}
var pascal=UsePascalCase(text)
return(
<>
<textarea onChange={handleOnInputEntry}></textarea>
<span>{pascal}</span>
</>
)
}
The input box,where want to use the hook
export default function UsePascalCase(str){
var firstCharacter=str.charAt(0).toUpperCase();
var restCharacters=str.substring(1).toLowerCase();
var sentence=firstCharacter+restCharacters
return sentence
}
Your text variable needs to be reactive to see changes in your application. More info: https://reactjs.org/docs/hooks-state.html
Try:
import UsePascalCase from "../CustomHooks/UsePascalCase"
import { useState } from "react"
export default function TextBoxDemo(){
const [text, setText] = useState("");
function handleOnInputEntry(e){
setText(e.target.value)
}
var pascal=UsePascalCase(text)
return(
<>
<textarea onChange={handleOnInputEntry}></textarea>
<span>{pascal}</span>
</>
)
}

vue3 how to use suspense passing async props to component

I've been learning about suspense but I still don't figure out how to use it in my use case.
I understand how to use it when you have a component which has the responsibility to fetch data itself, but I show a legacy example which I don't know how to migrate:
ExampleView.vue
<template>
<skeleton-component v-if="isLoading && !hasError">
<alert-component v-if="hasError">
<example-sub-component v-if="!isLoading && !hasError" :data=data />
</template>
<script setup>
const isLoading = ref(true)
const hasError = ref(false)
const data ref(null)
fetchData().then((response) => {
data.value = response
}).catch((e) => {
hasError.value = e
}).finally(() => {
isLoading.value = false
})
</script>
ExampleSubComponent.vue
<template>
{{data}}
</template>
<script setup>
defineProps([data])
</script>
Can I use suspense to simplify my code? I thought suspense would remove all this kind of logic about loading and showing/hiding errors.
But the only way I see to accomplish this is moving the fetchData logic inside ExampleSubComponent but I don't like this approach... In my use case I feel it's the view who has to fetch the data and pass down to components.
I tried this code but not working... suspense is looking for ExampleSubComponent to be async but it's not, the only async logic is the fetchData.
ExampleView.vue
<template>
<suspense>
<template #default>
<example-sub-component v-if="!hasError" :data=data />
<alert-component v-if="hasError">
</template>
<template #fallback>
<slot name="fallback">
<skeleton-component>
</slot>
</template>
</suspense>
</template>
<script setup>
const hasError = ref(false)
const data ref(null)
await fetchData().then((response) => {
data.value = response
}).catch((e) => {
hasError.value = e
})
</script>
I will need to still write this loading/showing hiding errors logic in every view?

Custom Component in Laravel Spark

I try to add my custom component to my Laravel Spark instance and always get the error:
Property or method "obj" is not defined on the instance but referenced during render..
It all works fine if i only bind a data value (ex. "testkey") without a loop...but if i add the for loop i receive this error...so my code:
app.js (spark)
require('spark-bootstrap');
require('./components/bootstrap');
//my new Component
import OmcListObjects from './components/modules/omc/objectlist.vue';
Vue.component('omc-objectlist', OmcListObjects);
var app = new Vue({
mixins: [require('spark')]
});
my Component (objectlist.vue)
<template>
<div :for="(obj in objlist)" class="property-entry card col- col-md-4 shadow-sm">
</div>
</template>
<script>
export default {
data () {
return {
objlist: [{title: 'test1'}, {title: 'test2'}],
testkey: 'testval'
}
}
}
</script>
I think you mean by :for the v-for directive, directives are always prefixed by v- like v-for one in which the compiler can recognize the obj variable as an temporary element used in the loop, but if you set :for which is recognized as a prop bound to a data or another property.

How do I trigger a reaction when bind:this is used in {#await} in Svelte?

Let us say that I want to have a little UI overlay that points to a DOM element (let us call it "Tap Here"). To get the location of where it should point to: I use bind:this and it works, unless I don't use it in {#await}.
<script>
import TapHere from './TapHere.svelte';
let enableButton;
$: enableButtonRect = enableButton && enableButton.getBoundingClientRect();
let promise = new Promise((resolve) => {
setInterval(resolve, 3000);
});
</script>
{#await promise}
<p>
waiting...
</p>
{:then}
<div>
<button bind:this={enableButton}>Enable</button>
<button>Disable</button>
<TapHere rect={enableButtonRect}/>
</div>
{/await}
https://svelte.dev/repl/4e0e477d6a394a83a2d79b3d1fa50525?version=3.12.1
(enableButtonRect may be a bit of red-herring as this problem manifests it with just trying to pass in enableButton itself to TapHere.) If you remove await, the TapHere goes to the intended location; but with await, TapHere does not get triggered by the enableButtonRect change. What should I do here?
Somehow enableButton is undefined within the promise resolve block even after the promise resolves.
However, if you evaluate enableButton outside of the block, it is correctly undefined while the promise is still pending, and correctly set to [object HTMLButtonElement] once the promise resolves.
There must be an explanation for this behavior, but I do not know it. Hopefully someone can elaborate.
So you can achieve the result you want by moving the <TapHere> component outside the promise block:
<script>
import TapHere from './TapHere.svelte';
let enableButton;
$: enableButtonRect = enableButton && enableButton.getBoundingClientRect();
let promise = new Promise((resolve) => {
setInterval(resolve, 3000);
});
</script>
{#await promise}
<p>
waiting...
</p>
{:then}
<div>
<button bind:this={enableButton}>Enable</button>
<button>Disable</button>
</div>
<p>Inside promise resolve block: {enableButton}</p>
{/await}
<p>Outside promise resolve block: {enableButton}</p>
<TapHere rect={enableButtonRect}/>
Edit
To show the tooltip after a promise resolves, you could do the following:
<script>
import { onMount } from 'svelte';
import TapHere from './TapHere.svelte';
let enableButton;
let disabled = true;
$: enableButtonRect = enableButton && enableButton.getBoundingClientRect() && !disabled;
onMount(() => {
const interval = setInterval(() => { disabled = false }, 3000)
return () => clearInterval(interval)
})
</script>
<div>
<button bind:this={enableButton} {disabled}>Enable</button>
<button>Disable</button>
<TapHere rect={enableButtonRect}/>
</div>
(REPL updated)
https://svelte.dev/repl/e647bc2b1a024e8885ebb96317887710?version=3.12.1

react not receiving prop from html

I have a react component in a file named ts.js:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
export default class Ts extends React.Component {
constructor(props) {
super(props);
var expected = {
lowercase:'Onlylowercase',
snakeCase:'justSnakeCase',
ProperCase: 'AndProperCase'
};
console.log("expected:",expected);
console.log("props:",props);
console.log("this.props",this.props);
console.log("props.lowercase",props.lowercase);
this.state={'lowercase':this.props.lowercase};
};
render() {
return NULL;
}
}
if (document.getElementById('ts')) {
ReactDOM.render(<Ts />, document.getElementById('ts'));
}
I also have a html page from where this is called:
<html>
<head>
<title>My TS</title>
</head>
<body>
<Ts lowercase="onlylowercase" id="ts" snakeCase="justSnakeCase" ProperCase="AndProperCase">
</Ts>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
My issue is I can't get the values lowercase="onlylowercase" id="ts" snakeCase="justSnakeCase" ProperCase="AndProperCase" recognised as props in the constructor. I need to pass in some stuff from the html to populate the initial state of the component.
When I open the HTML with Chrome console open I get:
expected: {lowercase: "Onlylowercase", snakeCase: "justSnakeCase", ProperCase: "AndProperCase"}
props: {}
__proto__: Object
or it is this.props?: {}
__proto__: Object
props.lowercase undefined
this.props.lowercase undefined
undefined
undefined
I am expecting props to be a javascript object with properties of lowercase, snakeCase and ProperCase, like the var expected.
I don't think I need to use componentWillReceiveProps - as I am trying to follow the pattern describe in the documentation here:
https://reactjs.org/docs/react-component.html#constructor
and pass in props as html attributes as described here:
https://reactjs.org/docs/components-and-props.html
I have excluded from this post the detail of the node modules and javascript includes - as the Ts component's constructor is being called which demonstrates the Ts class is "there" and my npm config is OK - it is including react and other required modules. The {{ asset() }} function is a Laravel function. The html is part of a blade template in a Laravel app.
Can anyone see what I am doing wrongly?
Your syntax is wrong. React doesn't creat a new html tag like "". You only can use tag in react component. So the right syntax is in html replace
<Ts lowercase="onlylowercase" id="ts" snakeCase="justSnakeCase" ProperCase="AndProperCase">
</Ts>
To <div id="ts"></div>
and go add to before
<script>
var lowercase="whatever";
var snakeCase="snakeCase";
...
</script>
And change to
if (document.getElementById('ts')) {
ReactDOM.render(<Ts lowercase={lowercase} snakeCase={snakeCase} />, document.getElementById('ts'));
}
ReactDOM will find a dom with id is "ts" and replace it by your ts component.

Resources