I' am creating a Vue component that shows an SVG image from my node modules based on a given image name or key (given by an API).
If I put the source image directly like ~cryptocurrency-icons/svg/color/eur.svg, the resource loads.
But if I try to compute it with the props or by the mounted method asigning it using :src="imageSource" it does not load.
I'm new to Vue so I don't know why is this happening? Should I use images downloaded in a public directory instead of the NPM package?
<template lang="html">
<img src="~cryptocurrency-icons/svg/color/eur.svg" alt="icon" />
</template>
<script lang="js">
export default {
name: 'crypto-icon',
props: ['currency'],
mounted() {
this.imageSource = `~cryptocurrency-icons/svg/color/${this.currency}.svg`
},
data() {
return {
imageSource: ""
}
},
methods: {
getImageResource(){
return `~cryptocurrency-icons/svg/color/${this.currency}.svg`
}
},
computed: {
}
}
</script>
<style lang="scss" scoped>
.crypto-icon {}
</style>
You are missing the require attribute. Vue Loader, does this automatically when it compiles the <template> blocks in single file components. Try with this:
require(`~cryptocurrency-icons/svg/color/${this.currency}.svg`)
You can read more here.
I've solved it by using a Vue plugin (see vue-cryptoicons), although hatef is right about using require for image resources, using it in directories under node_modules tries to find the full path
~cryptocurrency-icons/svg/color in ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a7e19d86-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Wallet.vue?vue&type=template&id=7f1455a9&scoped=true&lang=html&
To install it, you can run: npm install --save ~cryptocurrency-icons/svg/color
Related
I have a static asset - png image. I was able to use it like:
<img class="navbar-brand" id="navbar-logo" src="#/assets/logo.png">
But I need it to be possible to replace after deployment. When I put image in public folder and use an absolute path vue application not shows image.
<img class="navbar-brand" id="navbar-logo" src="/logo.png">
The img tag presents on page and browser executes http call for image. The response code is 200 but response body is empty. The image file stored in public folder, which is in root folder of vue application. Actually even if I put in src attribute the name of image which not exist I get a 200 response code, which is strange.
I also have a router in my application and it seems to be working fine, but I not sure can it cause the problem or not:
export default new Router({
mode: 'history',
routes: [
{
path: '/:dataset([^/0-9]+?)',
name: 'introduction',
component: Introduction
},
{
path: '/:dataset([^/0-9]+?)/introduction',
name: 'introduction',
component: Introduction
},
{
path: '/:dataset([^/0-9]+?)/sample-data',
name: 'sample-data',
component: SampleData
},
{
path: '/404',
component: NotFound
},
{
path: '*',
component: NotFound
}
]
})
I run application on my workstation with
npm run dev
The vue version is:
front#1.0.0 /home/pm/git/showroom/front
└── vue#2.6.11
Please help to show image from public folder.
I am trying to build a Blockly Application using Angular. I installed Blockly using npm . I also added the following scripts in angular.json
"scripts": [
"node_modules/blockly/blockly_compressed.js",
"node_modules/blockly/blocks_compressed.js",
"node_modules/blockly/python_compressed.js",
"node_modules/blockly/msg/en.js"
]
Though i can use import * as Blockly from 'blockly' to import blockly in the application and use other functions, I am not able to find Generator functions like Blockly.Python['text_indexOf']
I am using blockly: ^3.20200625.2 and #angular/cli: ~9.1.0 versions.
Am i missing something. Can anyone help me with this issue?
I've had the same problem with electron+angular app building, the next solution had helped me.
Blockly's reference says that Python's generator class should be included with file python_compressed.js right after blockly_compressed.js. So I need to include these files.
First I've used copy-webpack-plugin to copy needed files from Blockly's install directory node_modules/blockly to assets/js:
var CopyPlugin = require('copy-webpack-plugin');
module.exports = {
...
plugins: [
...
new CopyPlugin([
{
from: 'node_modules/blockly/blockly_compressed.js',
to: 'assets/js/[name].[ext]'
},
{
from: 'node_modules/blockly/blocks_compressed.js',
to: 'assets/js/[name].[ext]'
},
{
from: 'node_modules/blockly/python_compressed.js',
to: 'assets/js/[name].[ext]'
},
{
from: 'node_modules/blockly/msg/en.js',
to: 'assets/js/msg/[name].[ext]'
},
]),
...
]
...
}
After I've added scripts calling from js/assets directly from index.html's bottom:
<!DOCTYPE html>
<html>
<head>...</head>
<body><app-root>...</app-root></body>
<script src="assets/js/blockly_compressed.js"></script>
<script src="assets/js/blocks_compressed.js"></script>
<script src="assets/js/python_compressed.js"></script>
<script src="assets/js/msg/en.js"></script>
</html>
After webpack build check python's generator in console:
> typeof Blockly.Python
< "object"
I'm trying to set up in Angular a way of only showing Twitch player if the stream is online, so in the Documentation there is this inline HTML:
<script src= "https://player.twitch.tv/js/embed/v1.js"></script>
<div id="<player div ID>"></div>
<script type="text/javascript">
var options = {
width: <width>,
height: <height>,
channel: "<channel ID>",
video: "<video ID>",
collection: "<collection ID>",
};
var player = new Twitch.Player("<player div ID>", options);
player.setVolume(0.5);
</script>
Of course though in Angular Components we can't use < script > tags and I don't think it's currently possible to use require or import to use this in my components TypeScript.
So how would I go about adding this functionality? I understand what to do after I can actually reference that script tag.
You can create a script tag dynamically, but I think it's easier to just download the script and put it in assets folder and then add the script to script list in angular.json
or you can add the script to index.html head section
index.html
<head>
<script src= "https://player.twitch.tv/js/embed/v1.js"></script>
...
</head>
add this to component ngOninit method
ngOnInit() {
var options = {
width: <width>,
height: <height>,
channel: "<channel ID>",
video: "<video ID>",
collection: "<collection ID>",
};
var player = new Twitch.Player("<player div ID>", options);
player.setVolume(0.5);
}
Component template
<div id="<player div ID>"></div>
You may find another solution like angular package for twitch can be more cleaner way
Updated
typescript will give an error like [ts] Cannot find name 'Twitch'. [2304] some library has type definition files but in our case if you use Twitch object in this file only you can add this statement to tell typescript about the Twitch object
declare const Twitch: any;
if you want to use Twitch on multiple components
src/global.d.ts
declare const Twitch: any;
final recommendation
install npm i twitch-js and import Twitch object like this
import Twitch from 'twitch-js'
this will be bundled by webpack, so you don't need to add any script tag in the html.
twitch-devs
Struggled with this for a while. My script was asynchronous, and eventually I discovered postscribe package. Works like magic.
npm install --save postscribe
In the code:
import postscribe from 'postscribe'
//The script you want to load
const script = '<script src="https://darksky.net/map-embed/#radar,41.88,-87.62,10.js?embed=true&timeControl=false&fieldControl=false&defaultField=radar"></script>';
postscribe('#yourDivName', script);
This is how I made it work:
Copy everything from Twitch JS URL.
Create file twitch.js in your assets folder and paste everything. ( src/assets/scripts/twitch.js ).
In your component add import Twitch from 'src/assets/scripts/twitch.js'.
Also in your component add the twitch init code
Your component should look like this:
import { Component, OnInit } from '#angular/core';
import Twitch from 'src/assets/scripts/twitch.js';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
embedTwitch! : any;
constructor() { }
ngOnInit() {
this.embedTwitch = new Twitch.Embed("twitch-embed", {
width: 854,
height: 480,
channel: "monstercat"
});
}
}
Your component html must have twitch placeholder <div id="twitch-embed"></div>
Open your app and enjoy :)
Manually download the v1.js script from https://embed.twitch.tv/embed/v1.js
Create new folder src/twitch/ and add the v1.js script to it
Add "src/twitch/v1.js" to the scripts array in angular.json
Create a new file twitch.d.ts in src/twitch/
Add declare const Twitch: any; to twitch.d.ts
The Twitch library can now be used anywhere without importing any module like so:
ngOnInit(): void {
new Twitch.Embed('containerId', {
channel: 'asmongold',
height: 500,
width: 400,
});
}
I need to click on "login" which is inside span tag, code looks like
<div data-reactroot>
<div class "ant-dropdown ant-dropdown-placement-bottomRight ant-dropdown-hidden" style="left 632.234px; top 65px;">
<ul class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical" role="menu" style="border" 1px solid rgba(0, 0, 0, 0.23);">
<li class="ant-dropdown-menu-item" role="menuitem">...</li>
<li class=" ant-dropdown-menu-item-divider"></li>
<li class="ant-dropdown-menu-item" role="menuitem">...</li>
<span>Login</span>
</li>
https://i.stack.imgur.com/qDt4z.png
I tried using the code below, it does not work:
browser.driver.findElement(by.cssContainingText('ant-dropdown-menu-item', 'Login'))
I'm getting an error see below:
Message:
Failed: Invalid locator
Stack:
TypeError: Invalid locator
Try that:
browser.driver.findElement(by.cssContainingText('.ant-dropdown-menu-item', 'Login'))
In css selectors class need to have ..
Edit:
browser.driver.findElement(by.css('.ant-dropdown-menu-item > span'))
It's now working i'm tried using the following code below
element(by.xpath("//span[. = 'Login']")).click();
ReactJS testing made more simplifies with protractor-react-selector
protractor-react-selector is a lightweight plugin to help you to locate web elements in your REACT app using props and states.
You need to install the plugin with
npm i -D protractor-react-selector
Then, you need to add the plugin to the configuration file:
exports.config = {
// ... the rest of your config
plugins: [
{
package: 'protractor-react-selector'
}
]
}
Then, in a beforeAll`` hook or inside anonPrepare``` hook, wait for React to be loaded in your application like:
beforeAll(() => {
await browser.get('http://localhost:3000/myApp')
await browser.waitForReact()
})
Then you can use element(by.react) to fetch the react elements.
const myElement = element(
by.react('MyComponent', { someBooleanProp: true }, { someBooleanState: true })
)
myElement.click();
For testing the React element, you should not rely on the HTML DOM structure as most of the developers uses material tools that creates dynamic HTML runtime.
To find more example, visit these tests
A complete blog can be found here.
I'm using webpack with react, and I usually import and use my images as such:
import CalNotices from 'assets/img/calendar-notices.png';
<img className='img-center' role='presentation' src={CalNotices}/>
that works fine, and when I do production build, those images area neatly put into appropriate folders.
However, at times, I want to use images for backgrounds, and use it as such:
const divStyle = {
backgroundImage: `url(${item.logo})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center'
}
<div className='image-holder' style={divStyle}></div>
with item.logo being an absolute path to the image.
This works fine in dev, but when I do a prod build, those images are obviously missing, since they didn't get picked up by the webpack image loader. How should I approach this?
my image loader config is
{
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
include: [paths.appSrc, paths.appNodeModules],
loader: 'file',
query: {
name: 'static/media/[name].[ext]'
}
},
Based on your comments (all of the images are in /src/assets/img/logos), you can leverage webpack's require.context functionality to bundle the entire logo folder at build time:
// causes webpack to find and bundle *all* files in logos or one of its subfolders.
const logoContext = require.context("assets/img/logos", true, /\.(png|jpg)$/);
// later...in your render() method
// assumes item.logo is a path relative to the logos folder
// example: "credit-card-xxx.jpg" or "./credit-card-xxx.jpg"
const logoUrl = logoContext.resolve(item.logo);