I want to use autocomplete.js in my application.
I have installed the package using yarn add #tarekraafat/autocomplete.js. I am using webpack 4.28 to bundle the javascript files and have require("#tarekraafat/autocomplete.js/dist/js/autoComplete"); to import the package into the application and placed the bundled file at the bottom before the closing BODY tag.
In my custom.js file, I am creating a new instance of autoComplete as follows:
new autoComplete({
data: {
src: async () => {
document.querySelector("#autoComplete_results_list").style.display = "none";
document.querySelector("#autoComplete").setAttribute("placeholder", "Loading...");
const source = await fetch("/employee/search");
const data = await source.json();
return data;
},
key: "name"
},
selector: "#autoComplete",
placeHolder: "type employee name to search...",
threshold: 0,
searchEngine: "strict",
highlight: true,
dataAttribute: { tag: "value", value: "" },
maxResults: Infinity,
renderResults: {
destination: document.querySelector("#autoComplete"),
position: "afterend"
},
onSelection: feedback => {
document.querySelector(".selection").innerHTML = feedback.selection.food;
document
.querySelector("#autoComplete")
.setAttribute("placeholder", `${event.target.closest(".autoComplete_result").id}`);
console.log(feedback);
}
});
However, on running the application, I am getting an error Uncaught ReferenceError: autoComplete is not defined with a reference to the location where I am creating the new instance.
I have read the getting started documentation and looked at the demo code and I can't figure out what I am missing. How do I resolve the error?
Your problem is in your import, you are not import the autoComplete correctly, so when you using the new autoComplete you are having error.
Change the require("#tarekraafat/autocomplete.js/dist/js/autoComplete"); to import autoComplete from '#tarekraafat/autocomplete.js';, put this on top of your file, right after jquery or something
Write your code inside
$(document).ready(function(){
// Write your Code Here
});
Related
I am using the jsPDF library for converting a table into a PDF file.
The current code that I have used is giving off an error, that autoTable is not a function.
Here is the code.
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel",
"sap/ui/core/util/Export",
"sap/ui/core/util/ExportTypeCSV"
],
function (Controller, JSONModel, Export, ExportTypeCSV) {
"use strict";
return Controller.extend("c.g.modalproject1.controller.Root", {
onInit: function () {
var oModel1 = new JSONModel("./model/vegetableDataJSON.json");
this.getView().setModel(oModel1, "veg");
console.log("data : ", oModel1);
},
openDialog1: function () {
if (!this.pdialog1) {
this.pdialog1 = this.loadFragment({
name: "c.g.modalproject1.fragments.mTables"
});
}
this.pdialog1.then(function (oDialog) {
oDialog.open();
})
new sap.m.MessageToast.show("Table Loaded");
},
closeDialog: function () {
this.byId("newDialog1").close();
sap.m.MessageToast.show("Table closed ! ");
// var vegTable = this.getView().byId("vegiesMTable");
// vegTable.setGrowing(false);
// vegTable.setGrowingScrollToLoad(false);
},
downloadCSV: function () {
// Show a toast message to indicate that the file is downloading
sap.m.MessageToast.show("Downloading Excel..");
// Create a new Export object with the specified export type and options
var oExport = new Export({
exportType: new ExportTypeCSV({
separatorChar: ","
}),
models: this.getView().getModel("veg"),
rows: {
path: "/vegetablesRootNode"
},
columns: [{
name: "Title",
template: {
content: "{title}"
}
},
{
name: "Type",
template: {
content: "{type}"
}
},
{
name: "Description",
template: {
content: "{description}"
}
},
{
name: "Price",
template: {
content: "{price}"
}
},
{
name: "Rating",
template: {
content: "{rating}"
}
}]
});
// Save the file and handle any errors that may occur
oExport.saveFile().catch(function (oError) {
sap.m.MessageToast.show("Error when downloading data. Browser might not be supported!\n\n" + oError);
}).then(function () {
// Destroy the export object
oExport.destroy();
});
},
downloadPDF:function()
{
sap.m.MessageToast.show("Downloading into PDF started !");
var oModel2 = this.getView().getModel("veg");
console.log("check data = ", oModel2);
var oColumns = ["Title","Type","Description","Price","Rating"];
var oRows = [];
oRows = oModel2.oData.vegetablesRootNode;
console.log(oColumns);
console.log(oRows);
//var pdfDoc = new jsPDF('p', 'pt', 'letter');
var pdfDoc = new jsPDF();
pdfDoc.text(20, 20, "Vegetables Table");
pdfDoc.autoTable(oRows, oColumns);
pdfDoc.save("test.pdf");
//pdfDoc.output("save","t.pdf");
}
});
});
The last function is the code that runs to save the table data into PDF.
Can you please help.
These are the files that are included in my project folder.
Manifest.json
Adding just text, and most of the functionality that is available (via methods) from jsPDF works fine. I have created PDFs with just text from this app as well.
It works fine for adding text and downloads fine. But for Table data, it doesnt work.
I tried various ways but didn't get to solve it at all.
I tried to make a POC with this library and it works :-)
Configure the framework so that it can load the libraries
sap.ui.loader.config({
// activate real async loading and module definitions
async: true,
// load thirparty from cdn
paths: {
"thirdparty/jsPDF": "https://unpkg.com/jspdf#2.5.1/dist/jspdf.umd.min",
"thirdparty/jsPDFautoTable": "https://unpkg.com/jspdf-autotable#3.5.28/dist/jspdf.plugin.autotable"
},
// provide dependency and export metadata for non-UI5 modules
shim: {
"thirdparty/jsPDF": {
amd: true,
exports: "jspdf"
},
"thirdparty/jsPDFautoTable": {
amd: true,
exports: "jspdf",
deps: ["thirdparty/jsPDF"]
}
}
});
You can put that code on top on your Component.js file
Idea is to configure the framework to load libraries from CDN as AMD module with dependencies.
It's a bit tricky in your case and I'm not sure I understand the mechanism; what I imagine is that autoTable is a jsPDF plugin so we need jsPDF (dependency); the plugin overload jsPDF and returns jsPDF object
For sap.ui.loader here the official doc. :
https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.loader/methods/sap.ui.loader.config
Loads and consumes libraries
sap.ui.require(["thirdparty/jsPDFautoTable"], (jsPDFautoTable) => {
var doc = new jsPDFautoTable.jsPDF();
doc.autoTable({ html: '#my-table' });
doc.save('table.pdf');
});
Either with sap.ui.define or sap.ui.require to load the library on the fly when needed
Problem
I am trying to inject / replace environment variables with #rollup/plugin-replace. Unfortunately, I get this error:
TypeError: can't convert undefined to object
Code
// rollup.config.js
import replace from "#rollup/plugin-replace";
import { config } from "dotenv";
config();
export default {
// ...
plugins: [
replace({
values: { YOUTUBE_API: JSON.stringify(process.env.YOUTUBE_API) },
preventAssignment: true,
}),
// ...
}
And I call it like this:
onMount(() => {
(async function getPopular() {
videos = await axios.get("https://www.googleapis.com/youtube/v3/videos", {
part: "id, snippet, suggestions",
chart: "mostPopular",
key: YOUTUBE_API,
});
})();
});
What I tried
I logged out the variable and so can confirm that it exists. Also, if I remove the stringify function, I get another error:
ReferenceError: blablabblub is not defined
I have done this successfully in other projects. What the heck is wrong here?
So after some digging around with the same issue, I found it was related to object assignment. For example:
export default {
// ...
plugins: [
replace({
values: {
env: {
API_URL: process.env.API_URL,
API_VERSION: process.env.API_VERSION,
}
},
preventAssignment: true,
}),
// ...
}
// in some JS or Svelte file
const config = {
host: env.API_URL,
version: env.API_VERSION
}
// The above will result in a reference error of 'env' not being defined.
// in the same JS or Svelte file..
const envVars = env;
const config = {
host: envVars.API_URL,
version: envVars.API_VERSION
}
// this works just fine!
I haven't had anymore time to investigate, but my gut feeling is that rollup won't replace variable names when they are nested inside an object assignment. It might be nice for an optional flag to allow this, but it might also get very messy hence why they didn't do it.
I hope this helps if it's still an issue for you.
Is there any way I can access a JS API exposed by a Nuxt module from within a client-side plugin?
Context: I'm using Buefy/Bulma, which is loaded like this in nuxt.config.js:
modules: [
['nuxt-buefy', {css: false}],
],
Buefy exposes this.$buefy.<etc> which is accessible from components.
But I want to access this API from within a client-side plugin, utils.js, which is loaded like this:
plugins: ['~/plugins/utils.js'],
And utils.js itself:
export default ({app}, inject) => {
inject('myUtil', (msg, isErr) => {
app.$buefy; //<-- undefined
....
I assume this is an ordering issue, i.e. Buefy is being loaded after my plugin or something. I can't do this in a static JS file loaded via meta.scripts as that won't have access to the app (I assume).
Anything I can do here?
Try this in your plugin js file
import { ToastProgrammatic as toast } from 'buefy';
export default (_, inject) => {
inject('appHelper', {
displayToast(duration = null, msg = null, position = null, type = null) {
toast.open({
duration: duration || 3000,
message: msg || 'Update Successful',
position: position || 'is-bottom-left',
type: type || 'is-success',
});
},
});
};
Consider the following code within gatsby-config.js:
module.exports = {
plugins: [
{
resolve: `gatsby-source-fetch`,
options: {
name: `brands`,
type: `brands`,
url: `${dynamicURL}`, // This is the part I need to be dynamic at run/build time.
method: `get`,
axiosConfig: {
headers: { Accept: "text/csv" },
},
saveTo: `${__dirname}/src/data/brands-summary.csv`,
createNodes: false,
},
},
],
}
As you can see above, the URL for the source plugin is something that I need to be dynamic. The reason for this is that the file URL will change every time it's updated in the CMS. I need to query the CMS for that field and get its CDN URL before passing to the plugin.
I tried adding the following to the top of gatsby-config.js but I'm getting errors.
const axios = require("axios")
let dynamicURL = ""
const getBrands = async () => {
return await axios({
method: "get",
url: "https://some-proxy-url-that-returns-json-with-the-csv-file-url",
})
}
;(async () => {
const brands = await getBrands()
dynamicURL = brands.data.summary.url
})()
I'm assuming this doesn't work because the config is not waiting for the request above to resolve and therefore, all we get is a blank URL.
Is there any better way to do this? I can't simply supply the source plugin with a fixed/known URL ahead of time.
Any help greatly appreciated. I'm normally a Vue.js guy but having to work with React/Gatsby and so I'm not entirely familiar with it.
I had similar requirement where I need to set siteId of gatsby-plugin-matomo dynamically by fetching data from async api. After searching a lot of documentation of gatsby build lifecycle, I found a solution.
Here is my approach -
gatsby-config.js
module.exports = {
siteMetadata: {
...
},
plugins: {
{
resolve: 'gatsby-plugin-matomo',
options: {
siteId: '',
matomoUrl: 'MATOMO_URL',
siteUrl: 'GATSBY_SITE_URL',
dev: true
}
}
}
};
Here siteId is blank because I need to put it dynamically.
gatsby-node.js
exports.onPreInit = async ({ actions, store }) => {
const { setPluginStatus } = actions;
const state = store.getState();
const plugin = state.flattenedPlugins.find(plugin => plugin.name === "gatsby-plugin-matomo");
if (plugin) {
const matomo_site_id = await fetchMatomoSiteId('API_ENDPOINT_URL');
plugin.pluginOptions = {...plugin.pluginOptions, ...{ siteId: matomo_site_id }};
setPluginStatus({ pluginOptions: plugin.pluginOptions }, plugin);
}
};
exports.createPages = async function createPages({ actions, graphql }) {
/* Create page code */
};
onPreInit is a gatsby lifecycle method which is executing just after plugin loaded from config. onPreInit lifecycle hook has some built in methods.
store is the redux store where gatsby is storing all required information for build process.
setPluginStatus is a redux action by which plugin data can be modified in redux store of gatsby.
Here the important thing is onPreInit lifecycle hook has to be called in async way.
Hope this helps someone in future.
Another approach that may work for you is using environment variables as you said, the URL is known so, you can add them in a .env file rather than a CSV.
By default, Gatsby uses .env.development for gatsby develop and a .env.production for gatsby build command. So you will need to create two files in the root of your project.
In your .env (both and .env.development and .env.production) just add:
DYNAMIC_URL: https://yourUrl.com
Since your gatsby-config.js is rendered in your Node server, you don't need to prefix them by GATSBY_ as the ones rendered in the client-side needs. So, in your gatsby-config.js:
module.exports = {
plugins: [
{
resolve: `gatsby-source-fetch`,
options: {
name: `brands`,
type: `brands`,
url: process.env.DYNAMIC_URL, // This is the part I need to be dynamic at run/build time.
method: `get`,
axiosConfig: {
headers: { Accept: "text/csv" },
},
saveTo: `${__dirname}/src/data/brands-summary.csv`,
createNodes: false,
},
},
],
It's important to avoid tracking those files in your Git repository since you don't want to expose this type of data.
I've some problem, in my project I need to add Sanitize.js on my project, I've copied to my own 3rd party folder ex vendor
to import it I'm using
import {san} from '../../vendor/Sanitize' //There's No error when compiling this one
but there's an error when I run the page, I'm trying to call the function from Sanitize.js as in readme saying to use it just do like this
var s = new san.Sanitize({
elements: ['a', 'span'],
attributes: {
a: ['href', 'title'],
span: ['class']
},
protocols: {
a: { href: ['http', 'https', 'mailto'] }
}
});
s.clean_node(p);
The Error is
san.Sanitize is not a function/ class constructor
Any idea why this is happening? or did I miss something? There's no Error in compiling process, the error only occurs when I try to run the web page,
Because Sanitize.js is not a module.
Maybe you can try the following solution:
Add export default Sanitize; in end of sanitize.js.
Use import Sanitize from "./sanitize"; to import it.
Remove the following code from sanitize.js.
if ( typeof define === "function" ) {
define( "sanitize", [], function () { return Sanitize; } );
}