package.json (question related dependencies)
"dependencies": {
"monaco-editor-webpack-plugin": "^1.9.1",
"splitpanes": "^2.4.1",
"vue-monaco": "^1.2.2"
}
vue.config.js
const MonacoEditorPlugin = require('monaco-editor-webpack-plugin')
module.exports = {
transpileDependencies: [
'vuetify'
],
configureWebpack: {
plugins: [
new MonacoEditorPlugin({
languages: ['javascript', 'typescript']
})
]
}
}
CodeEditor.vue
<template>
<Splitpanes
style="100vh"
class="default-theme"
>
<Pane size="40">
<!-- Very long text -->
</Pane>
<Pane size="60">
<MonacoEditor
style="width: 100%; height: 100%"
v-model="code"
theme="vs-dark"
language="javascript"
:options="options"
/>
</Pane>
</Splitpanes>
</template>
<script>
import { Splitpanes, Pane } from 'splitpanes'
import MonacoEditor from 'vue-monaco'
import 'splitpanes/dist/splitpanes.css'
export default {
components: {
Splitpanes,
Pane,
MonacoEditor
},
data () {
return {
code: 'const noop = () => {}',
options: {
automaticLayout: true
}
}
}
}
</script>
Monaco Editor doesn't resize, even though I set automaticLayout to true. What am I doing wrong?
Note: With monaco-editor-vue and monaco-editor-webpack-plugin 1.8.2 everything works fine (but I can't use it because it doesn't support v-model).
Related
I'm trying to run a component unit test on Nuxt 3 but I get an error telling me that the component cannot be found..
FAIL test/components/button.test.ts [ test/components/button.test.ts ]
Error: Failed to resolve import "#/components/Texts/Button/ButtonText.vue" from "components\Button\Button.vue". Does the file exist?
button.spec.ts
import {test, expect} from 'vitest';
import {mount} from '#vue/test-utils';
import Button from "../../components/Button/Button.vue";
test('Button Component', async () => {
const button = mount(Button, {
props: {
text: 'My Test Button'
}
});
expect(button.text()).toEqual('My Test Button');
});
Button.vue
<template>
<div class="Button">
<slot name="left" />
<ButtonText :text="text" />
<slot name="right" />
</div>
</template>
<script lang="ts">
export default {
name: 'Button',
components: {ButtonText},
props: {
// Text to display in the button
text: {
type: String as () => string,
default: 'Button',
required: true,
},
}
}
</script>
any ideas ?
Assuming, that #/components/Texts/Button/ButtonText.vue actually exists, a solution to your problem might be adding aliases to your ./vitest.config.ts like that:
// vitest.config.ts
import { defineConfig } from 'vite'
import { aliases } from './aliases'
export default defineConfig({
resolve: { aliases },
// ... further settings
})
// aliases.ts
import { resolve } from 'path';
const r = (p: string) => resolve(__dirname, p);
export const alias: Record<string, string> = {
'~~': r('.'),
'~~/': r('./'),
'##': r('.'),
'##/': r('./'),
// ... other aliases
};
I am currently using quasar v2(vuejs3) and the gold-layout 2.5.0 version.
(I also tried vue-golden-layout, but I gave up because it was difficult to use in quasar v2)
project structure
components
- TestCom.vue : simple component with only div and h2
- WebEditor.vue : part where the monaco editor is defined, and it works normally when the golden layout is not used.
layouts
- GoldenLayout.vue : The page where I want to use the Golden-layout package.
App.vue
I imported other components in Golden Layout.vue and registered in Golden-layout.
There is no error message when running, but the contents of the components are not visible.
Is there a right way to register the component in Golden layout?
layouts/GoldenLayout.vue
<template>
<div>
<link type="text/css" rel="stylesheet" href="//golden-layout.com/assets/css/goldenlayout-base.css" />
<link type="text/css" rel="stylesheet" href="//golden-layout.com/assets/css/goldenlayout-light-theme.css" />
<div ref ="test"></div>
</div>
</template>
<script>
import {shallowRef , ref, onMounted, onUnmounted, h } from "vue";
import { GoldenLayout } from "golden-layout/src/index";
import WebEditor from "components/WebEditor.vue";
import TestCom from "components/TestCom.vue"
export default {
name: 'App',
components: {
},
setup(props) {
let c = () => h(WebEditor, {
code : "import java.util.*;\nimport java.io.*;\n\npublic class Main{\n public static void main(String[] args) throws IOException {\n BufferedReader re = new BufferedReader(new InputStreamReader(System.in));\n \n int a = Integer.parseInt(re.readLine());\n int b = Integer.parseInt(re.readLine());\n\n System.out.println(a+b);\n re.close();\n }\n}",
language : "java",
readonly : false
});
let d = () => h(TestCom);
const test = ref(undefined);
let goldenLayout;
const config = {
content:
[
{
type: 'row',
content:
[
{
type: 'component',
componentName: 'WebEditor',
componentType : 'WebEditor'
},
{
type: 'component',
componentName: 'TestCom',
componentType : 'TestCom'
}
]
}
]
}
onMounted(() => {
goldenLayout = new GoldenLayout(test);
goldenLayout.registerComponent('WebEditor', c);
goldenLayout.registerComponent('TestCom', d);
goldenLayout.init();
goldenLayout.loadLayout(config);
});
onUnmounted(() => {
goldenLayout.destroy();
});
return {
test
};
}
};
</script>
<style scoped>
</style>
components/TestCom.vue
<template>
<div>
<h2 style="height:200px">Test</h2>
</div>
</template>
<script>
export default {
setup () {
return {}
}
}
</script>
<style lang="scss" scoped>
</style>
componets/WebEditor.vue
<template>
<div>
<div ref="editorDiv" style="height: 100%; width:100%"></div>
<div><h2 #click="updateEditor">refresh</h2></div>
</div>
</template>
<script>
// package.json
// "monaco-editor": "^0.33.0",
// "monaco-editor-webpack-plugin": "^7.0.1",
// quasar.confg
// const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
// module.exports = configure(function (/* ctx */) {
// return {
// plugins: [new MonacoWebpackPlugin()],
import { ref, onMounted } from "vue";
import * as monaco from 'monaco-editor';
export default {
// example
//
// <web-editor code="import java.util.*" language="java" :readOnly="false"></web-editor>
name : 'WebEditor',
props :{
code : String, // "import java.util.*;\nimport java.io.*;\n\npublic class Main{\n public static void main(String[] args) throws IOException {\n BufferedReader re = new BufferedReader(new InputStreamReader(System.in));\n \n int a = Integer.parseInt(re.readLine());\n int b = Integer.parseInt(re.readLine());\n\n System.out.println(a+b);\n re.close();\n }\n}"
language : String, // "java", "c", "python"
readOnly : Boolean, // "false"
},
setup (props) {
const editorDiv = ref(undefined);
let monacoEditor;
let editorCode = JSON.parse(JSON.stringify(props.code));
let editorLanguage = JSON.parse(JSON.stringify(props.language));
let editorReadOnly = JSON.parse(JSON.stringify(props.readOnly));
onMounted(() => {
monacoEditor = monaco.editor.create(editorDiv.value,{
// model: null,
readOnly: editorReadOnly,
value: editorCode,
language: editorLanguage,
// theme: 'vs', //light version
theme: 'vs-dark',
tabSize: 2,
fontFamily: "Consolas",
// fontFamily: 'D2Coding',
// fontFamily: 'IBM Plex Mono',
fontSize: 12,
});
});
const updateEditor = () => {
editorCode = monacoEditor.getValue();
monacoEditor.dispose();
monacoEditor = monaco.editor.create(editorDiv.value,{
// model: null,
readOnly: editorReadOnly,
value: editorCode,
// c,cpp,java,javascript,python
language: editorLanguage,
// theme: 'vs', //light version
theme: 'vs-dark',
tabSize: 2,
fontFamily: "Consolas",
fontSize: 12,
});
};
return {
editorDiv,
monacoEditor,
editorCode,
editorLanguage,
editorReadOnly,
updateEditor
};
}
}
</script>
<style lang="scss" scoped>
</style>
This is my first time asking a question in stackoverflow. If you feel that I made a mistake or lack explanation for the problem, please let me know right away.
I'm facing a issue with AG-grid in Storybook.
I'm trying to do filtration in AG-grid added as storybook template. But gridReady event doesn't get fired
Here is the code for reference
someApp.component.html
<div style="float: right; width: 100%;display: flex; <=== this is dive to have search field. We can add input here.
flex-direction: row;
justify-content: flex-end;">
<mat-search-bar (keyup)="applyFilter($event.target.value)" (onClose)="clearFilter()" [placeholder]="Search"></mat-search-bar>
</div> <===== on keyup it takes the input from search field and get the filter data in AG-Grid
</mat-toolbar>
<div class=" ag-grid-container">
<ag-grid-angular
class="ag-theme-material ag-grid-container"
[columnDefs]="columnDefs"
[rowData]="rowdef"
[suppressColumnMoveAnimation]="true"
[suppressDragLeaveHidesColumns]="true"
[overlayNoRowsTemplate]="overlayNoRowsTemplate"
(gridReady)="onGridReady($event)"
>
</ag-grid-angular>
In the above code, I get the value of search and call applyFilter to set quickfilter in grid
someApp.component.ts
columnDefs = [
{ headerName:'Sports', field: 'sports'},
{ headerName:'No: of Players', field:'player'},
];
gridApi!: GridApi;
Search = "Search";
onGridReady (params) {
console.log('calling grid Api');
this.gridApi = params.api;
console.log('called grid Api: '+this.gridApi);
}
ngOnInit() {
}
public overlayNoRowsTemplate =
'<div *ngIf="rowDef.length === 0" class="no-records">No database found.</div>';
applyFilter(value: string) {
console.log(value);
this.gridApi.setQuickFilter(
value
);
}
clearFilter() {
this.gridApi.setQuickFilter(""
);
}
someApp.stories.ts
import {
GridApi,
GridReadyEvent,
ICellRendererParams
} from 'ag-grid-community';
import { moduleMetadata, Meta } from '#storybook/angular';
import { ActionsComponent } from 'projects/web-component-library/src/lib/components/actions/app-actions.component';
import {someApp} from '../../projects/web-component-library/src/lib/components/inventory/inventory.component';
import { MaterialModule } from '../../projects/web-component-library/src/lib/components/material';
import { BrowserAnimationsModule, NoopAnimationsModule } from '#angular/platform-browser/animations';
import { NgMatSearchBarModule } from 'ng-mat-search-bar';
import { AgGridModule } from 'ag-grid-angular';
import { RouterModule } from '#angular/router';
import { CustomActionComponent } from 'projects/web-component-library/src/lib/components/custom-action/custom-action.component';
const rowdef = [{sports:'Cricket', player:11},
{sports:'Basketball', player:5}
]
export default {
title: 'Data Inventory',
component: someApp,
decorators: [
moduleMetadata({
declarations: [someApp,CustomActionComponent],
imports: [MaterialModule, BrowserAnimationsModule, NoopAnimationsModule,NgMatSearchBarModule,AgGridModule.withComponents([CustomActionComponent]),RouterModule]
}),
],
} as Meta;
export const Default = (args: someApp) => ({
component: someApp,
props: args
});
Default.args = {
rowdef
};
export const NoData = (args: someApp) => ({
component: someApp,
props: args
});
NoData.args = {
rowdef:[]
};
When I try to search something
it gives error as this.gridApi is undefined. whereas when I add this in parent HTML as below and run as 'ng serve', its works fine
App.component.html
<some-app><some-app>
Seems like onGridReady is not fired properly in storybook.
Using
Storybook 6.0.12
Angular 8
npm 6.13.4
node v10.19.0
Log of error in storybook
I have an MPA app, where vue.js is used as a part of the application. I have a very simple test set up, here:
relevant parts of my template
....
<div id='app-basket-checkout'>
<h1>Better Be Here</h1>
</div>
....
pageBasketCheckout.js (essentially my app.js)
import Vue from 'vue'
import AppBasketCheckout from './BasketCheckout.vue'
import './dummyScss.css'
Vue.config.productionTip = false
new Vue({
render: h => h(AppBasketCheckout)
}).$mount('#app-basket-checkout')
component
<template>
<div id="app-basket-checkout">
{{msg}}
</div>
</template>
<script>
export default {
name: 'AppBasketCheckout',
components: {
},
data() {
return {
msg: 'Hello'
}
}
}
</script>
<style scoped>
</style>
So the above code renders just fine in my front end. I end up with an extra div that has hello printed inside, well done.
However when I add css to the style tag:
<template>
<div id="app-basket-checkout">
{{msg}}
</div>
</template>
<script>
export default {
name: 'AppBasketCheckout',
components: {
},
data() {
return {
msg: 'Hello'
}
}
}
</script>
<style scoped>
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.4;
}
</style>
This produces this error in chrome:
Uncaught Error: Cannot find module './BasketCheckout.vue?vue&type=style&index=0&id=2711cf65&scoped=true&lang=css&'
at webpackMissingModule (VM45512 BasketCheckout.vue:4)
at eval (VM45512 BasketCheckout.vue:4)
at Module../src/BasketCheckout.vue (pageBasketCheckout.bundle.js:40)
at __webpack_require__ (index.bundle.js:4312)
at eval (pageBasketCheckout.js:3)
at Module../src/pageBasketCheckout.js (pageBasketCheckout.bundle.js:29)
at __webpack_require__ (index.bundle.js:4312)
at checkDeferredModulesImpl (index.bundle.js:4453)
at webpackJsonpCallback (index.bundle.js:4435)
at pageBasketCheckout.bundle.js:9
Again this error only happens when adding css to the component. Here is my webpack.config.js:
const path = require('path');
const webpack = require('webpack')
const glob = require('glob')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
watch: true,
context: path.resolve(__dirname, 'uniquesite/uniquesite'),
mode: 'development',
entry: {
index: {
import: ['#babel/polyfill', './src/index.js'],
// dependOn: ['babel'],
},
pageProductDetails: {
import: ['#babel/polyfill', './src/pageProductDetails.js'],
dependOn: ['index'],
},
pageBasketCheckout: {
import: ['#babel/polyfill', './src/dummyScss.scss', './src/pageBasketCheckout.js'],
dependOn: ['index']
}
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'uniquesite/uniquesite/static/uniquesite/js/'),
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
alias: {
jquery: "jquery/src/jquery",
'jquery-ui': "jquery-ui-dist/jquery-ui.js",
boostrap: "bootstrap/dist/js/bootstrap.bundle.js"
}
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader'
},{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
};
You'll note I've also tried importing a dummy .css file to ensure the style loader works, as I've seen one more SO question with a similar problem that solved it that way. That didn't work for me however.
Update 1
My current thinking is that the problem has to be happening in the VueLoaderPlugin. That plugin is reponsible for splitting the script into distinct parts for template, logic, and style. It looks like the style is not actually making it into the bundle. See below.
"use strict";
eval(
"__webpack_require__.r(__webpack_exports__);
/* harmony import */
var _BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
/*! ./BasketCheckout.vue?vue&type=template&id=2711cf65& */
\"./src/BasketCheckout.vue?vue&type=template&id=2711cf65&\"
);
/* harmony import */
var _BasketCheckout_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
/*! ./BasketCheckout.vue?vue&type=script&lang=js& */
\"./src/BasketCheckout.vue?vue&type=script&lang=js&\"
);
Object(function webpackMissingModule() {
var e = new Error(
\"Cannot find module './BasketCheckout.vue?vue&type=style&index=0&lang=css&'\"
); e.code = 'MODULE_NOT_FOUND';
throw e;
}());
/* harmony import */
var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */
\"../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"
);
/* normalize component */
var component = (
0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__.default
)(
_BasketCheckout_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__.default,
_BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__.render,
_BasketCheckout_vue_vue_type_template_id_2711cf65___WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
false,
null,
null,
null)
/* hot reload */
if (false) { var api; }
component.options.__file = \"src/BasketCheckout.vue\"
/* harmony default export */
__webpack_exports__[\"default\"] = (component.exports);
//# sourceURL=webpack:///./src/BasketCheckout.vue?"
);
Scoped CSS rules only apply to the current component (and its child components' root nodes).
You are mounting your Vue instance at #app-basket-checkout, which is already inside a <body> element.
You can style <body>, but do it using a global stylesheet that is imported in your app.js, not a subcomponent.
Alternatively, you can apply a class-based style at a low level node within your Vue instance and likely deliver your desired styles.
I have a component:
import React from 'react';
import * as styles from './RedComponent.css';
class RedComponent extends React.Component {
render () {
return <div className={ styles.red }></div>;
}
}
This is the test case:
describe('Test suite', () => {
test('RedComponent tests', () => {
const wrapper = shallow(<RedComponent />);
});
console.log(wrapper.debug());
gives
<div className={[undefined]}></div>
instead of
<div className="RedComponent__red"></div>
If I console the imported styles I get
console.log(styles); // {default: {}}
This is only in Jest test cases. Style is not undefined when the app renders in browser.
My jest config:
{
"moduleFileExtensions": [
"js"
],
"moduleDirectories": [
"node_modules"
],
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy"
},
"setupFiles": [
"./test-setup.js"
],
"collectCoverageFrom": [
"src/**/*.{js}",
"!**/node_modules/**"
],
"testEnvironment": "node",
"transform": {
"^.+\\.js$": "babel-jest",
"\\.(md|ttf|txt|eot|ico|otf|svg|png|gif|woff2|woff|jpeg)$": "./file-transformer.js"
}
}
Using jest v21.2.1, identity-obj-proxy v3.0.0 and React v16.0.0.
You have to change this line
import * as styles from './RedComponent.css';
to this:
import styles from './RedComponent.css';
I assume that you are using css-loader or similar and this is just how the loader works.
Maybe worths to check the example:
https://github.com/keyanzhang/jest-css-modules-example/
I think your moduleNameMapper should be like this:
"^.+\\.(css|less)$": "identity-obj-proxy"
Create a jest/identity-obj-proxy-esm.js file with the following content:
// This works around the fact we use ES named exports for styles, e.g.:
// import * as styles from './styles.scss'.
// https://github.com/keyanzhang/identity-obj-proxy/issues/8
module.exports = new Proxy(
{},
{
get: function getter(target, key) {
if (key === '__esModule') {
// True instead of false to pretend we're an ES module.
return true;
}
return key;
},
},
);
Edit jest.config.js:
// jest.config.js
module.exports = {
...
moduleNameMapper: {
...
'\\.(css|scss)$': '<rootDir>/jest/identity-obj-proxy-esm.js',
}
};
🏆 João Vieira and https://github.com/keyz/identity-obj-proxy/issues/8#issuecomment-430241345