Laravel & Vuejs Integration - Vuejs mixins - javascript

I'm trying to create a mixin to handle my sweetalerts2 logic. Now, i've created a mixin named sweetAlerts.js inside a folder: assets/js/misins and i wrote the next block of code inside of it:
import swal from 'sweetalert2'
export default {
methods: {
$sAlert(data) {
swal(data)
},
$sToast(data) {
swal.mixin(data)
},
}
};
Then i've imported it on my app.js file like this:
import sweetAlerts from './mixins/sweetAlerts'
Vue.mixin(sweetAlerts)
The problem is that methods like this one doesn't work:
methods: {
launchAlert() {
this.$sAlert(data)
}
}
I know that sweetalerts2 works just fine because i've tested it inside my application. The main problem is that i can't create a mixin with all the alerts logic to implement it on any component i want.
Is there a solution for it ?

Related

using vuejs mixins in js file

i have a system in which i have to set up some reusable functions to be used all over my application, now i have created a vue mixin in my main main.js file now when i call that function from vue components it works just fine but when i try to call the same function inside a js file i get an error of undefined here's my code
main.js
Vue.mixin({
methods: {
test: function () {
return 1;
},
}
});
Vue Components
//this works
async created() {
alert(this.test());
}
services.js
import { API } from 'aws-amplify';
import { Auth } from "aws-amplify";
import axios from 'axios'
export default {
somefunction(){
//this doesnot work
alert(this.test());
}
}
can someone tell me how can i use vue mixins in regular js files, i looked on the internet but couldn't find anything related to this
// mixin.js
export myMixin = { computed: { foo(): 'hi' } }
Simply create an object (and likely mark it as an export) besides adding it to vue.
It's just an object. It has special names like computed, data etc. in it, but it's just an object.
// usage.vue
import { myMixin } from './path/to/myMixin.js'
console.log( myMixin.computed.foo ) // hi
export default {
mixins: [ myMixin ],
computed: { bar(): { this.foo } // hi
}
In the above example, I'm not using a global mixin, because, to quote vue docs
Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components.
Now, if you really need a global mixin, that's why it's for, but note that to use myMixin outside of vue export default, you'd need to access it via global scope, like window, or import it like above. For more info refer to queries like these: global functions in js.
My preference:
// in a file at /path/to/index.js
export { myMixin1 } from './myMixin1' // ...
// usage.vue
import { myMixin1, myMixin2 } from './path/to'
export default { mixins: [ ... ] }
or alternatively where needed, (because mixins can include other mixins ;) though I find it harder to use them in other JS then
export myMixin1 = { ... }
export myMixin2 = {
mixins: [ myMixin1 ]
// ...
}
// usage.vue
import { myMixin2 } from 'path/to/myMixins'
export default {
mixins: [ myMixin2 ] // contains both 1 and 2
}
Note you can also declare in Vue files (single file components), and then import from them just as they were Javascript.
Also, you (obviously) don't need to export them - they're already useful for separating concerns.
// example.vue
<script>
export myMixin = { ... }
// all mixins can interact with each other
// because in the end, they will be parts of the same object
myToggle = { ... }
mySuperComplicatedBit = { ... }
// so B can call this.A
export default {
mixins: [
myMixin,
myToggle,
mySuperComplicatedBit
],
...
}
</script>
<template> ...
// other.vue or other.js
import { myMixin } from 'path/to/example.vue'
Cheers and good luck
If your mixin is generic you could use a global mixin and access it via the main application. But I don‘t really see the point, then why have a mixin in the first place?
main.js
export default new Vue({
mixins: [YourMixin]
...
})
somecode.js
import vue from ‚./main.js‘
vue.method()
Edit: suggestion
To be honest, I‘d rather turn your implementation around and have a service expose a functionality, which is then integrated to the Vue components via a mixin.
You can call methods in mixins only in Vue components. The role of the mixin is to extend the vue component. I would extract the logic from your mixin in a separate service or utility js and then use it in the mixin and service.js

Vue error with Rangy library: "..." is not a function (but only inside hooks)

For a Vue component, I use the Rangy library to highlight single words inside a text. This is working fine if Rangy is called from any method inside the methods object:
let applier = rangy.createClassApplier('some-class');
applier.toggleRange(range);
But sometimes I need to restore a certain state on page load, so I tried using the same method inside the created and mounted hooks. This doesn't work.
Right now, the first lines of the script in my component look like this:
import _ from 'lodash';
import rangy from 'rangy';
import 'rangy/lib/rangy-classapplier';
export default {
mounted: function() {
// Leave function if there is no data in DB to be restored
if (_.isEmpty(this.mostRecentAnswers))
return;
else {
// ERROR
let applier = rangy.createClassApplier('some-class');
// ...
}
}
// ...
}
The error message is TypeError: rangy__WEBPACK_IMPORTED_MODULE_2___default.a.createClassApplier is not a function at VueComponent.mounted
I use Vue with Laravel and Laravel Mix (which is a wrapper for Webpack).
What's wrong with my code? Note I also import Lodash and use it inside the hook without any errors.
I would recommend making a Vue plugin out of this to make it easier:
// plugins/vue-rangy.js
import rangy from 'rangy'
const VueRangy = {
install (Vue, options) {
if (options.hasOwnProperty('init') && options.init) {
rangy.init()
}
Vue.prototype.$rangy = rangy
}
}
export default VueRangy
Then use it like any other plugin:
import VueRangy from 'plugins/vue-rangy'
Vue.use(VueRangy, {
init: true
})
Then just use this.$rangy in your components.
I had to use rangy.init() which initializes Rangy if it has not already been initialized:
https://github.com/timdown/rangy/wiki/Rangy-Object#rangyinit

Set a global service for import in Create React App

Is it possible to somehow declare a jsx file as a global file or a directory for import? For example instead of:
import { Navigation } from '../../../../../../helpers/NavigationService';
do just:
import { Navigation } from 'NavigationService';
I've seen it's possible in webpack config, but I don't see this file in create-react-app. Can I use somehow package.json for that?
There are three ways to solve your issue:
NODE_PATH (<- probably what you're looking for):
You can define an environment variable NODE_PATH=src/ and then you can import your service like so import { Navigation } from 'helpers/NavigationService';. It'll will work but this is not necessary what's best in my opinion.
No deep nesting:
No nesting, means no issue of deep nesting in the first place. You can try having a file hierarchy similar to this:
src/
/helpers
/components/
/componentA/
componentA
relatedComponent
otherRelatedComponent <- no need for nesting
/componentB/
...
The mono repo approach:
Having an internal helper package and have it imported like import { Navigation } from 'myproject-helpers/NavigationService'; may be a good compromise
You could set NODE_PATH='src' in .env file, using global imports instead, here's my solution, without having to eject.
.env:
NODE_PATH='src'
Create a folder src/services, inside it create the NavigationService, my example:
// src/services/NavigationService.js
export class NavigationService {
static runIt() {
console.log("Running");
}
}
In the App.js file, now you can import the navigation service directly, using global import, as follows:
// src/App.js
// ... import React and others
import { NavigationService } from "services/NavigationService";
class App extends Component {
componentDidMount() {
NavigationService.runIt();
}
// ... render method
}
If using VsCode, to get code completion, create jsconfig.json file, with the following:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"services/*": ["./src/services/*"]
}
}
}
I hope it helps!

How to import node module in React-Kotlin?

I created an app using the create-react-kotlin-app command and it loads in Chrome fine. I added the React Material UI package via NPM and that was successful. Now how do I use the Material UI module in my component?
Normally with JavaScript, it's a simple import Button from '#material-ui/core/Button' at the top of the component's file, but Kotlin doesn't like that.
How do I translate that line to Kotlin? I am not using Gradle.
I have been struggling with this problem for days now. I came up with the following solution. First we will see multiple ways to declare external modules, then I will show how to use them
.
Consider the following javascript code
import Button from '#material-ui/core/Button' // this means button is exported as default
This will be imported in kotlin in the following ways
Button.kt
#file:JsModule("#material-ui/core/Button")
#file:JsNonModule
package com.mypckage.mykillerapp
import react.Component
import react.RProps
import react.RState
import react.ReactElement
#JsName("default") // because it was exported as default
external val Button : RClass<RProps>
// way 2
#JsName("default")
external class Button : Component<RProps,RState> {
override fun render(): ReactElement?
}
But again, if the statement intend for kotlin has to match the javascript import statement bellow,
import { Button } from "material-ui" // not exported as default
We use the following approach: Button.kt
#file:JsModule("material-ui")
#file:JsNonModule
package com.mypckage.mykillerapp
import react.Component
import react.RProps
import react.RState
import react.ReactElement
// way 1
#JsName("Button") // because it was exported as default
external val Button : RClass<RProps>
// way 2
#JsName("Button")
external class Button : Component<RProps,RState> {
override fun render(): ReactElement?
}
once you have declared on how to use your components, you can just use them as follows:
//way 1:
fun RBuilder.render() {
div {
Button {
attrs.asDynamic().className="submit-button"
+"Submit"
}
}
}
//way 2:
fun RBuilder.render() {
div {
child(Button::class) {
attrs.asDynamic().className="submit-button"
+"Submit"
}
}
}
great. you have imported your component. But until then your are not relying on kotlin type safety and even code completion, to achieve that, you have to go to extra length
as shown bellow
external interface ButtonProps: RProps {
var className : String
var onClick: (Event?)->Unit
var color: String
// . . .
var href: String
}
then go ahead and declare your button as
#JsModule("#material-ui/core/Button")
#JsNonModule
#JsName("default") // because it was exported as default
external val Button : RClass<ButtonProps>
and you can now use it with type safety and code completion as shown bellow
fun RBuilder.render() {
div {
Button {
attrs {
className = "submit-button"
onClick = {
window.alert("Vois La")
}
}
+"Submit"
}
}
}
Hope this helps. Happy coding
EDIT:
There is a community wrapper for material-ui components here
HINT:
Use way 1, as you can see, it is less verbose
The Kotlin way for importing dependencies is close to standard JS importing:
import React from 'react';
export function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Based on Creating a simple React component with Kotlin.
package hello
import react.*
import react.dom.*
fun RBuilder.hello(name: String) {
h1 {
+"Hello, $name"
}
}
Usually (as Kotlin is Java-based) it uses Gradle tool to handle dependencies:
// part of build.gradle
kotlinFrontend {
// ...
npm {
// ...
dependency("react")
dependency("react-dom")
dependency("react-router")
dependency("react-markdown")
devDependency("css-loader")
devDependency("babel-core")
// ...
}
And are referenced like above:
HomeView.kt:
// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/HomeView.kt
import kotlinx.html.*
import org.jetbrains.demo.thinkter.model.*
import react.*
import react.dom.*
import kotlinx.coroutines.experimental.launch
ReactMarkdown.kt:
// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/ReactMarkdown.kt
package org.jetbrains.demo.thinkter
import react.*
private val ReactMarkdown: dynamic = runtime.wrappers.require("react-markdown")
Based on: kotlin-fullstack-sample
In create-react-kotlin-app additionally faced the possibility of importing with #JsModule() annotation, while dependencies managing is handled in standard way via package.json:
// src/logo/Logo.kt (outcome of creating new app)
package logo
import react.*
import react.dom.*
import kotlinext.js.*
import kotlinx.html.style
#JsModule("src/logo/react.svg")
external val reactLogo: dynamic
#JsModule("src/logo/kotlin.svg")
external val kotlinLogo: dynamic
And can be also successfully used for JS libraries importing.
Another way would be to use kotlinext.js.*:
// index/index.kt
import kotlinext.js.*
fun main(args: Array<String>) {
requireAll(require.context("src", true, js("/\\.css$/")))
// ...
}
Which provides also require(module: String) function.

Cleanest way to import/require a Vue.js directive?

I'm trying to organize my plugins into custom Vue Directives that could be a simple as:
Vue.directive('popout', {
bind() {
$(this.el).popOut();
}
});
And save these in separate files, to be imported in either the main JS file or the Vue(ify) components with something like:
require('./directives/popout.js');
I've tried a number of export default setups, but I can't seem to get it to work. What would be the cleanest (i.e. best-practice) way to do this?
I got the solution,below is the code
import Vue from 'vue';
export const global= {
bind(el, binding, vnode) {
console.log('you code');
}
};
this code goes in lets say directive/global.js file.
Then in you app.js or entry point file use this
import { global } from './directive/global.js';
Vue.directive('global', global);
first line will import the directive as we are using same name to only used global, second line to make you directive global. Hope it help.

Categories

Resources