I am using Vue js in my javascript code. I downloaded the vue-star-rating npm package to have a rating system for one of my elements. I believe I have followed the instructions here correctly, but I am getting the error
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link type="text/css" rel="../css/ProductEvaluation.css" />
</head>
<body>
<button class="btn btn-sm" id="btnRun">Run</button>
<div id="product-eval-areas">
<ul>
<li v-for="area in areas">
{{area.EvaluationArea}}
// Error is occurring on this custom element
<star-rating v-model="area.ProductEvaluationScore"></star-rating>
</li>
</ul>
</div>
<script src="https://url.com/WebResources/ccseq_/Scripts/jquery3.1.1.js"></script>
<script src="../../Scripts/papaparse.js"></script>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script src="../../Scripts/require.js" data-main="../js/main/ProductEvaluation.js"></script>
</body>
</html>
.js
"use strict";
requirejs.config({
bundles: {
'https://url.com/WebResources/ccseq_/WebResources/js/lib/CCSEQ.WebAPI.js': ['Model/ProductEvaluation', 'Model/ProductEvaluationArea', 'API/ProductEvaluation', 'API/ProductEvaluationArea']
//'../lib/CCSEQ.WebAPI.js': ['Model/ProductEvaluation', 'Model/ProductEvaluationArea', 'API/ProductEvaluation', 'API/ProductEvaluationArea']
}
});
require(["Model/ProductEvaluation", "Model/ProductEvaluationArea", "API/ProductEvaluation", "API/ProductEvaluationArea", "../../../node_modules/vue-star-rating/dist/star-rating.min"], function (ProductEvaluationModel, ProductEvaluationAreaModel, ProductEvaluationAPI, ProductEvaluationAreaAPI, StarRating) {
var currentProductEvaluation = new ProductEvaluationModel.ProductEvaluation();
Vue.component('star-rating', StarRating);
var areas = new Vue({
el: '#product-eval-areas',
data: { areas: currentProductEvaluation.ProductEvaluationAreas }
})
$(document).ready(function () {
PopulatePage();
});
function PopulatePage() {
$("#btnRun").click(function () {
var productEvaluationAPI = new ProductEvaluationAPI.ProductEvaluation();
productEvaluationAPI.Get(window.parent.Xrm.Page.data.entity.getId().replace(/({|})/g, "")).
then(
function (results) {
LoadProductEvaluation(results);
console.log("success");
}).catch(function (results) {
console.log("Fail");
});
});
}
function LoadProductEvaluation(productEvaluation) {
productEvaluation.ccseq_ccseq_productevaluation_ccseq_producteval.forEach(function (pe) {
var newProductEvaluationArea = new ProductEvaluationAreaModel.ProductEvaluationArea();
newProductEvaluationArea.EvaluationArea = pe.ccseq_evaluationarea;
newProductEvaluationArea.ProductEvaluationScore = pe.ccseq_productevaluationscore;
newProductEvaluationArea.SelfEvaluation = pe.ccseq_selfevaluation;
newProductEvaluationArea.ProductEvaluationID = pe.ccseq_productevaluationid;
currentProductEvaluation.ProductEvaluationAreas.push(newProductEvaluationArea);
});
}
});
This is my package, but I didn't document how to use it with requireJS as I haven't used it in quite a few years. It is however bundled as a named UMD module which is defined as "VueStarRating" so you need to add the following to your requirejs config:
paths: {
'VueStarRating': '../../../node_modules/vue-star-rating/dist/star-rating.min'
}
Then you can do:
require(['VueStarRating'], function(StarRating) {
Vue.component('star-rating', StarRating.default);
new Vue({
el: '#app'
})
});
You can check it out on this JSFiddle: https://jsfiddle.net/2Lgz9vs4/
If you run into further trouble then it might be worth tagging your questions with requirejs aswell. Most Vue developers use CommonJS (including myself) so you should get better responses there.
Related
Context
I've created a two column page, one column with a button on the left and editorJS on the right column.
What I am trying to do is whenever I click on the button to the left, I want it to be copied into a new block of EditorJS.
Replication
The error triggers whenever trying to add a new block manually (in this case, an extertal button to add more content to EditorJS) using editor.blocks.insert(blockToAdd). Independently of the configuration of the EditorJS, even the most basic one will trigger this error.
Code
index.js (I've modified this file to make it shorter, the error always trigger in the same place which is
const blockToAdd = {
type: 'paragraph',
data: {
text: 'My header'
}
};
editor.blocks.insert(blockToAdd); // Here
Actual file
const btn = document.getElementById('export-btn')
const editor = new EditorJS({
/**
* Id of Element that should contain Editor instance
*/
onReady: () => {
new DragDrop(editor);
},
holder: 'editorjs',
tools: {
header: {
class: Header,
config: {
placeholder: 'Enter a header',
levels: [1,2,3,4],
defaultLevel: 3
}
},
paragraph: {
class: Paragraph,
inlineToolbar: true,
}
},
});
function saveEditor() {
editor.save().then( savedData => {
fetch('http://localhost:3000', {
method: 'POST',
body: JSON.stringify(savedData),
headers: {
'Content-Type': 'application/json'
}
}).then( msg => {
console.log(msg)
}).catch( err => {
console.error(err)
})
console.log()
})
.catch( err => {
console.error(err)
})
}
btn.addEventListener('click', function() {
const blockToAdd = {
type: 'paragraph',
data: {
text: 'My header'
}
};
editor.blocks.insert(blockToAdd);
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Testing EditorJS and Docx</title>
</head>
<body>
<div class="col-left">
<div id="export-btn" class="export-btn">Export to...</div>
</div>
<div class="col-right">
<div id="editorjs"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest"></script>
<script src="https://cdn.jsdelivr.net/npm/#editorjs/header#latest"></script>
<script src="https://cdn.jsdelivr.net/npm/#editorjs/list#latest"></script>
<script src="index.js"></script>
</body>
</html>
Error
Uncaught TypeError: can't access property "name", s is undefined
S https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest:6
value https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest:6
value https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest:6
<anonymous> https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest:6
<anonymous> file:///E:/wdev/tasktag-dashboard-ui/index.js:105
EventListener.handleEvent* file:///E:/wdev/tasktag-dashboard-ui/index.js:97
editorjs#latest:6:44399
Error screenshot
Where could the problem be at? Because I am using <script src="https://cdn.jsdelivr.net/npm/editorjs-drag-drop#latest"></script> sort of imports?
Otherwise, I don't know what the problem is. Thank you in advance.
So the problem was in the object I pass to the editor.blocks.insert(blockToInsert).
It requires to pass option by option instead a single object. So the correct solution would be:
const blockToAdd = {
type: 'paragraph',
data: {
text: 'My header'
}
};
editor.blocks.insert(blockToAdd.type, blockToAdd.data);
Thanks Thomas from a JavaScript Telegram community for helping me out to resolve this problem.
I am not sure how to access a model I create with my controller with Vue in my html. I know how to access model attributes with thymeleaf, but cannot find any info anywhere on how to access them with Vue. I would like to store the count value from the controller in the Vue data count I have below. I am using Vue within my template hosted with CDN, not as a separate project.
Here is my controller:
#PostMapping("/word")
public String searchSentence(#ModelAttribute WordSearch wordSearch, Model model) {
int c = wordSearch.search();
String count = String.valueOf(c);
model.addAttribute("wordSearch", wordSearch);
model.addAttribute("count", count);
return "count";
}
Here is the count.html:
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Count-Form</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<h1>Result</h1>
<p th:text="'sentence: ' + ${wordSearch.sentence}" />
<p th:text="'word: ' + ${wordSearch.word}" />
<!--<p th:text="'count: ' + ${count}" /> -->
<div id="count-text" style="display: none">
<p th:text="${count}" />
</div>
<div id="app">
{{count}}
</div>
<script>
new Vue({
el: '#app',
data() {
return {
count: ""
}
},
created() {
this.count = ???
}
})
</script>
Submit another message
</body>
</html>
You can follow this blog to do what you desire. https://dev.to/brunodrugowick/spring-boot-vue-js-axios-and-thymeleaf-with-bootstrap-in-4-commits-2b0l. In this author explains how you can use Thymeleaf and VueJS together by adding VueJS dependency in pom.xml.
you need following dependency in your pom xml to use VueJS,
<dependency>
<groupId>org.webjars</groupId>
<artifactId>vue</artifactId>
<version>2.6.11</version>
</dependency>
Thymeleaf is a server-side Java template engine, while Vue is a JS framework to build frontend layer. The best way to connect Spring with Vue would be by an API.
So you'll need to expose your data as a JSON, make a http call vue app -> java api and consume the response.
Here you can find more details, how this works
All you have to do is create a method returning ResponseBody, then you call this method in Vue (Axios is a good option!).
Example 1: function to get a String variable:
#GetMapping( "/getLanguage")
#ResponseBody
public String obtenerIdiomaActual() {
return languageService.getLanguage();
}
Then you'd need a method in your Vue app to read this value:
const vm = Vue.createApp({
data() {
return {
language: null,
}
},
methods: {
getLanguage() {
axios.get(window.location.origin + '/getLanguage')
.then(response => {
this.language = response.data;
})
.catch(error => {
this.errorMessage = error.message;
console.error("There was an error!", error);
});
},
mounted: function () {
this.getLanguage();
},
watch: {
idioma: function () {
console.log("Language: " + this.language);
}
},
}).mount('#myApp')
You can use all kind of complex data: objects, arrays, dictionaries (maps)...
#GetMapping( "/getComplexData")
#ResponseBody
public Map<String, List<SpaceBean>> getMyComplexData() ...
And read the response easily with Vue:
<div v-for="(spaceList, key) in datos">
<p v-cloak><b>{{key}}</b></p>
<table class="display" style="width: 100%" v-cloak>
<tbody>
<tr v-for="space in spaceList">
<td>{{space.alias}}</td>
<td>{{space.descripcion}}</td>
<td>{{space.url}}</td>
</tr>
...
I hope this help a little!!
I would like to render several div containers depending on a returned API call from axios/vue. The axios call and callback work just fine, but vue won't render any divs.
Since I am using Django, I already changed the delimiters from curly brackets (which is Django default as well).
Error message in console:
Property or method "data" is not defined on the instance but referenced during render.
Make sure that this property is reactive, either in the data option,
or for class-based components, by initializing the property.
Please find a minimal code snippet as follows (if you remove the JS part the html will show up):
Thank you in advance for your help!
var app = new Vue({
delimiters: ['[[', ']]'],
el: '.EUR_Quotes',
data: {
info: []
},
created() {
axios
.get("http://data.fixer.io/api/latest?access_key=XXXd&base=EUR")
.then(response => {
this.info = response.data.rates;
console.log(response);
});
}
});
.EUR_Quotes {
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<html>
<head>
</head>
<body>
<div v-for="rates in info">
<div class="EUR_Quotes">[[ data ]]
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</html>
You are confusing your data variable name, it should be info in your template, (not data) the actual data object is the container for all your vuejs app's data.
Check the snippet, it works fine.
var app = new Vue({
delimiters: ['[[', ']]'],
el: '.EUR_Quotes',
data: {
info: []
},
created() {
axios
.get("http://data.fixer.io/api/latest?access_key=d&base=EUR")
.then(response => {
this.info = response.data.rates;
console.log(response);
});
}
});
.EUR_Quotes {
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<html>
<head>
</head>
<body>
<div v-for="rates in info">
<div class="EUR_Quotes">[[ info ]]
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</html>
I want to call my notification function from other JS file but it always return undefined.
notification.js
function notification(message, level = 'success') {
Lobibox.notify(level, {
delayIndicator: false,
msg: message
});
}
addToCart.vue
<template>
<div>
<button class="button dark small" #click="addToCart(menu, price)">
<i class="fa fa-cutlery fa-lg m-right-5"></i>
Pilih Menu
</button>
</div>
</template>
<script>
export default{
props: ['menu', 'price'],
methods:{
addToCart(menu, price){
const currentPoint = $('#current_point').val();
if(price > currentPoint){
return notification('Point is not enough', 'error')
}
}
}
}
</script>
app.js
Vue.component('addtocart', require('./components/AddToCart.vue'));
new Vue({
el: '#app'
});
html:
<script src="{{ asset('js/notification.js') }}"></script>
<script src="{{ asset('js/app.js') }}"></script>
Every time price > currentPoint get called it always return me Uncaught ReferenceError: notification is not defined.
I compile it using LaravelMix.
Any solution?
notification.js
function notification(message, level = 'success') {
Lobibox.notify(level, {
delayIndicator: false,
msg: message
});
}
window.notification = notification;
Solve it. I need to add window.notification = notification so I can call it everywhere.
It seems you just need to do following in your HTML:
<script src="js/notification.js"></script>
<script src="js/app.js"></script>
it's better to avoid putting things in window.
It looks like you're using the Vue with webpack. If you're not, then this won't work. If you are, you're better off using ES6 modules to make sure you have access to things where you need them.
Within your notification.js file:
export default user
Which you can then call on
import notification from 'notification'
I am learning VueJS 2.0 and I am connecting to an API where I want the value of some data to change on input change. Here is what the output says using the dev tools:
canadianDollar:undefined
europeanEuro:undefined
europeanPound:undefined
usd:"1232"
Whenever I put 1232 in the USD input field it doesn't return anything and leaves those properties as undefined. Here is the code.
new Vue({
el: '#app',
data: {
usd: '',
canadianDollar: '',
europeanPound: '',
europeanEuro: ''
},
// Watch methods
watch: {
usd: function() {
this.convertCurrency()
}
},
// Logic Methods
methods: {
convertCurrency: _.debounce(function() {
var app = this;
if (app.usd.length !== 0) {
// Show that the things are loading in.
app.canadianDollar = 'Searching...'
app.europeanPound = 'Searching...'
app.europeanEuro = 'Searching...'
console.log(app.usd)
axios.get("http://api.fixer.io/latest?base=USD&" + app.usd)
.then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
.catch(function(error){
app.canadianDollar = "ERROR"
app.europeanPound = "ERROR"
app.europeanEuro = "ERROR"
})
}
}, 500)
}
})
and the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Vue</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" name="" value="" v-model="usd">
<ul>
<li>Canadian Dollar: {{canadianDollar}}</li>
<li>European Pound: {{europeanPound}}</li>
<li>European Euro: {{europeanEuro}}</li>
</ul>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" charset="utf-8"></script>
<script src="index.js" charset="utf-8"></script>
</body>
</html>
When I type in a number it does give me the "Searching" part but disappears and nothing shows up.
I would recommend changing
then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
to
then(function(response) {
console.log(response);
})
that was you can see what is being returned.
Also, axios.get("http://api.fixer.io/latest?base=USD&" + app.usd) should probably have a name like vulue:axios.get("http://api.fixer.io/latest?base=USD&VALUE=" + app.usd), but you'll have to check their api to see what it is meant to be called.
...
response.data.rates.CAD;
you have
response.data.CAD;
...
app.canadianDollar = response.data.rates.CAD * app.usd;