Trix editor with livewire and alpine - javascript

So i have a working trix editor i can store it to database no problems with that.
But i have 2 issues.
problem 1
Error: Cannot read properties of undefined (reading 'loadHTML')
problem 2
data is not loaded in the editor using wire model.
For problem 1 i found solution to remove the warnings but data is not being loaded :
setValue() { if(this.$refs.trix.editor) this.$refs.trix.editor.loadHTML(this.value) },
For the second problem if i use a cdn like this it all works no errors no loading data problems so is there a problem in my code or is it my app.js what can i do to fix this? :
<script src="https://cdnjs.cloudflare.com/ajax/libs/trix/1.3.1/trix.min.js"></script>
App.js
import Trix from "trix";
window.Trix = Trix;
import './bootstrap';
import moment from "moment";
import Pikaday from 'pikaday';
import Alpine from 'alpinejs';
moment().format();
window.moment = moment;
window.Pikaday = Pikaday;
window.Alpine = Alpine;
Alpine.start();
component
<div
class="rounded-md shadow-sm"
x-data="{
value: #entangle($attributes->wire('model')),
isFocused() { return document.activeElement !== this.$refs.trix },
{{-- setValue() { this.$refs.trix.editor.loadHTML(this.value) },--}}
setValue() { if(this.$refs.trix.editor) this.$refs.trix.editor.loadHTML(this.value) },
}"
x-init="setValue(); $watch('value', () => isFocused() && setValue())"
x-on:trix-change="value = $event.target.value"
{{ $attributes->whereDoesntStartWith('wire:model') }}
wire:ignore>
<input id="x" type="hidden">
<trix-editor x-ref="trix" input="x" class="trix-editor form-textarea block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"></trix-editor>

Related

How to use a vue3 component(vue.draggable.next) inside Nuxt 3 project as a plugin

In my recently started project, I wanted to use a vue.draggable.next. So I created a ".js" file inside the nuxt plugin directory and I add code as below.
import VueDraggableNext from "vue-draggable-next";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueDraggableNext);
});
Then I used it in one of my components as below,
<template>
<div class="h-full w-full border-2 border-dashed rounded-lg p-5 flex">
<div class="flex w-1/6 h-full">
<ComponentPalette />
</div>
<VueDraggableNext
v-model="form.children"
group="people"
#start="isDragOver = true"
#end="isDragOver = false"
item-key="id"
class="flex flex-col w-5/6 h-full border-blue-700 border-2 border-dashed rounded-lg p-5 space-y-5"
>
<template #item="{element}">
<FormBuilder
:component="element"
#update="update"
/>
</template>
</VueDraggableNext>
</div>
</template>
<script setup>
import FormBuilder from "~~/components/dynamic-components/FormBuilder.vue";
import ComponentPalette from "~~/components/form-builder/ComponentPalette.vue";
import { v4 as uuidv4 } from "uuid";
const form = reactive({
formId: "abcd-1234",
formName: "User Registration",
children: [],
});
const isDragOver = ref(false);
</script>
<style scoped></style>
once I run the project I will get following errors:
[Vue warn]: A plugin must either be a function or an obj
ect with an "install" function.
[Vue warn]: Failed to resolve component: VueDraggableNex
t
If this is a native custom element, make sure to exclude
it from component resolution via compilerOptions.isCust
omElement.
How can I use this vue plugin properly in a nuxt3 project?
have some differences between a Vue Plugin and a Nuxt Plugin. What you are trying to do is create a Nuxt Plugin to use a Vue Component. So in order to do this, you need to update your code to:
import { VueDraggableNext } from "vue-draggable-next";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("draggable", VueDraggableNext);
});
The difference is the way you are registering the component in vueApp. Also with this change, you will need to update the component name inside the html template to <draggable>
Here follow some useful links if you want to know more:
https://vuejs.org/guide/components/registration.html#global-registration
https://v3.nuxtjs.org/guide/directory-structure/plugins

ReferenceError: Cannot access uninitialized variable on Safari with Vue

I've been getting an error that is puzzling me. The error is ReferenceError: Cannot access uninitialized variable. and refers to the line const app = createApp(App):
// main.js
import {createApp} from 'vue';
import App from 'components/App.vue';
// ...
const app = createApp(App);
// App.vue
<template>
<template v-if="!started">
<Start #started="start" />
</template>
<template v-else-if="!loaded">
<Loading #loaded="loaded = true" />
</template>
<template v-else>
<Tip />
<Cutscene v-if="state.phase == 'INTRO'" />
<Interstitial v-if="state.phase == 'INTERSTITIAL'" />
<Planning v-if="state.phase == 'PLANNING'" />
<Stream v-else-if="state.phase == 'EVENTS'" />
<Report v-else-if="state.phase == 'REPORT'" />
<End :lose="true" v-else-if="state.phase == 'GAMEOVER'" />
<End :lose="false" v-else-if="state.phase == 'GAMEWIN'" />
</template>
</template>
<script>
import debug from '/src/debug';
import state from '/src/state';
import Tip from './tip/Tip.vue';
import Start from './Start.vue';
import Loading from './Loading.vue';
import End from './phases/End.vue';
import Cutscene from './phases/Cutscene.vue';
import Interstitial from './phases/Interstitial.vue';
import Report from './phases/Report.vue';
import Stream from './phases/events/Events.vue';
import Planning from './phases/planning/Planning.vue';
import AudioManager from '/src/audio/manager';
// Hacky
window.audioManager = new AudioManager();
if (!state.sound) {
window.audioManager.muted = true;
}
export default {
data() {
return {
state,
started: false,
loaded: false,
};
},
methods: {
start() {
this.started = true;
}
},
components: {
Tip,
Start,
Report,
Stream,
Planning,
End,
Loading,
Cutscene,
Interstitial,
},
}
</script>
I've stared at this a long time and it seems like all my variables are properly initialized. Looking at my logging, this error seems to only occur with Safari (mobile and desktop). I can't tell if this is specifically Vue-related or what. I'm using Vue 3.1.4.
In my case the issue was assigning the output of createApp to an exported variable and then importing and using it in another .ts file.
A workaround that avoids this bug is to use:
import { vueApp } from "./main";
const getVueApp = () => ((window as any).app as typeof vueApp);
After previously creating your app like so:
const app = createApp(App);
(window as any).app = app;
Then you can call something like getVueApp().$nextTick with no issues.
If don't use TypeScript, you can simply just reference window.app directly, the import and function wrapper are just to get proper type inference!

Why is my React code editor component not highlighted by PrismJs?

I just discovered PrismJs and it looks perfect. But for some reason, it doesn't highlight my code in following component :
import { useState, useEffect } from "react";
import Prism from "prismjs";
export default function EditCode() {
const [content, setContent] = useState("");
useEffect(() => {
Prism.highlightAll();
}, []);
useEffect(() => {
Prism.highlightAll();
}, [content]);
return (
<section className="codeGlobalContainer">
<textarea
className="codeInput"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<pre className="codeOutput">
<code className={`language-javascript`}>{content}</code>
</pre>
</section>
);
}
Is there anything missing to make it work ?
It's not specified on there npm page, but you need to download a themed CSS on there official site : PrismsJS
Then, you just move the CSS file to your directory and import it in your component as usual :
import "../../styles/prism.css";
as #FlowRan mentioned you need to import any theme you want to use
but
Note: you do not need to download the themes separately as they come with the package.
Import your theme in your file by using the import statement from-
'prismjs/themes/prism-{theme-name}.css';

semantic-ui-calendar-react flicker in .tsx

The calendar is flickering Using DateInput in .tsx files
Tried fixing the issue by Why datepicker flicker in React when focus in input field?
App1.tsx
import React, { useState } from "react";
import { DateInput } from "semantic-ui-calendar-react";
import "./styles.css";
import "semantic-ui-css/semantic.min.css";
export default function App1() {
const [date, setDate] = useState("");
const handleChange = (event, { name, value }) => {
setDate(value);
};
return (
<div className="App">
<p>
App1.tsx - Flicker Fixed after using animation=false but getting build
error
</p>
<div>
<DateInput
name="date"
placeholder="Date"
value={date}
popupPosition="top right"
onChange={handleChange}
animation={false}
/>
</div>
</div>
);
}
This throws error Type 'false' is not assignable to type 'SemanticTRANSITIONS'
CodeSandbox
Also, I tried to set the duration property to 0. This works intermittently when there is one DateInput, but I have multiple controls on the page if one of them is open and I open another one, the second one flickers.
If there is any other fix for the flickering, please let me know.
Fixed this issue by wrapping the DateInput inside a js component and consuming that component from the tsx file.
Set animation={''} for fixing the issue as animation={false} gives console errors.

VueJS + TS; Component property not binding

I am trying to bind a component property by setting the related component attribute to a value but it is not binding the value when inspecting with Vue devtools or when outputting the value into the HTML. The value remains to be set to the default value that is set on the component.
I event set a string attribute to just a static string and even that is not binding.
The component also isn't outputted into the html at all, besides the top level div, but the Vue devtools do detect the component in the dom.
Code:
Component HTML:
<style scoped lang="sass">
#import './discord-widget.scss';
</style>
<template>
<div>
<b-card bg-variant="dark" :header="`Currently online: ${widgetData.members.length}`" text-variant="white">
<div v-for="user in widgetdata.members" class="discord-member">
<img :src="user.avatar_url" alt="" class="d-inline-block">
<div class="d-inline-block align-top has-game" v-if="user.game">
<span>{{ user.username }}#{{user.discriminator}}</span>
<span><br />Playing <b>{{ user.game.name }}</b></span>
</div>
<div class="d-inline-block" v-else>
<span>{{ user.username }}#{{user.discriminator}}</span>
</div>
</div>
</b-card>
</div>
</template>
<script src="./discord-widget.ts"></script>
Component ts:
import Vue from "vue";
import { DiscordWidgetResult } from "../../models/discord";
import Component from "vue-class-component";
import { Prop } from "vue-property-decorator";
#Component
export default class DiscordWidgetComponent extends Vue {
#Prop(Object) public widgetdata: DiscordWidgetResult = {} as DiscordWidgetResult;
#Prop(String) public test: string = "";
async mounted() {
this.widgetdata.members = this.widgetdata.members.sort((a, b) => a.game ? -1 : b.game ? -1 : 0);
}
}
Parent HTML using the component:
<discord-widget :widgetdata="widgetdata" v-on:load="getWidgetData" :test="'test'" class="pull-right ml-auto p-2 d-none d-sm-none d-md-none d-lg-block sticky-top" />
Parent ts:
import Vue from "vue";
import { Provide } from "vue-property-decorator";
import { DiscordWidgetResult } from "../../models/discord";
import { discordWidgetService } from "../../boot";
export default class NopeGamingView extends Vue {
#Provide()
public widgetdata: DiscordWidgetResult = {} as DiscordWidgetResult;
async created() {
}
async getWidgetData() {
this.widgetdata = await discordWidgetService.GetGuildData();
console.log("get data");
}
}
So, turned out my error was quite a simple one but easy to overlook.
I had forgotten to put the '#Component' decorator on my 'NopeGamingView' which caused it to not be an actual component. If you encounter as similar problem make sure you have the decorator on your view.

Categories

Resources