-
-
Notifications
You must be signed in to change notification settings - Fork 928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
img tags lose props on nested components #2321
Comments
Here my TypeScript for the Image Cache: Sorry if the script is based for mobile app building with capacitor. But it works as well while developing on the normal browser. import { Directory, Encoding, Filesystem } from '@capacitor/filesystem';
import { Preferences } from '@capacitor/preferences';
import path from 'path';
const CACHE_KEY = 'cached-images';
let observer;
let cacheData;
let saveRequired;
class ImageCache extends HTMLImageElement {
constructor() {
super();
if (this.hasAttribute('clear')) {
clearCacheData();
}
if (this.hasAttribute('lazy')) {
observer.observe(this);
}
else {
setSource(this);
}
}
}
(function () {
observer = new IntersectionObserver(intersectionCallback);
window.customElements.define('img-cache', ImageCache, { extends: 'img' });
requestIdleCallback();
})();
function intersectionCallback(entries, observer) {
entries.forEach(entry => {
console.log(entry);
if (entry.isIntersecting /*&& !entry.target.src*/ && entry.target.url) {
setSource(entry.target);
}
});
}
function requestIdleCallback() {
window.requestIdleCallback(saveCacheData, { timeout: 3000 });
}
function setSource(node) {
let url = node.getAttribute('url');
let mySrc = node.getAttribute('src');
let expire = node.getAttribute('expire');
console.log("setSource", url, mySrc, expire)
if (!url) {
url = mySrc;
}
console.log("setSource", url, expire)
makeLink(url, expire).then(link => node.src = link);
}
async function clearCacheData() {
await Preferences.remove({ key: CACHE_KEY });
cacheData = [];
}
async function loadCacheData() {
let obj = await Preferences.get({ key: CACHE_KEY });
cacheData = (obj.value ? JSON.parse(obj.value) : []);
}
async function saveCacheData() {
if (saveRequired) {
saveRequired = false;
await Preferences.set({ key: CACHE_KEY, value: JSON.stringify(cacheData) });
}
requestIdleCallback();
}
async function makeLink(url, expiration) {
if (!cacheData) {
await loadCacheData();
}
let index = findIndex(url);
let isCached = index != -1;
if (isCached && isExpired(cacheData[index].expiration)) {
await deleteFile(cacheData[index].file);
removeFromList(index);
isCached = false;
}
try {
if (!isCached) {
throw new Error();
}
return await readFile(cacheData[index].file);
}
catch (error) {
return await downloadImage(url, expiration);
}
}
function findIndex(url) {
return cacheData.findIndex(entry => entry.url == url);
}
function isExpired(expiration) {
return expiration && Date.now() > (new Date(expiration)).getTime();
}
async function readFile(filename) {
let contents = await Filesystem.readFile({ path: filename, directory: Directory.Cache, encoding: Encoding.UTF8 });
return contents.data;
}
async function writeFile(filename, data) {
return await Filesystem.writeFile({ path: filename, data: data, directory: Directory.Cache, encoding: Encoding.UTF8 });
}
async function deleteFile(filename) {
return await Filesystem.deleteFile({ path: filename, directory: Directory.Cache });
}
function removeFromList(index) {
cacheData.splice(index, 1);
saveRequired = true;
}
function addToList(url, filename, expiration) {
let date = (expiration ? (new Date(Date.now() + expiration * 60000)).toISOString() : null);
cacheData[cacheData.length] = { file: filename, expiration: date, url: url };
saveRequired = true;
}
async function downloadImage(url, expiration) {
let response = await fetch(url);
let blob = await response.blob();
let link = await blobToBase64(blob);
let filename = uid() + path.extname(url);
await writeFile(filename, link);
addToList(url, filename, expiration);
return link;
}
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
function uid() {
return Math.random().toString().substr(-8) + Date.now().toString().substr(-12);
} |
When in need to control if something is a prop or an attribute, you can use any of the following: Trying to guess, I suppose A playground repro would be welcome |
@titoBouzout thank you, I have now created a own Image Tag, that catch the informations via
this works for now, but I still have problems with the I'm missing maybe as its my first time with solidjs some examples that are showing how it works, the ones I have checked and tried to update, where all 2+ years old and broken... |
Attributes are case-insensitive, I cannot seem to be able to reproduce, the attributes are rendered Included in the link an example on how to type |
@Dexus Is this still an issue? |
Describe the bug
I have some some images with like:
one script I use which will run as custom element and is included globaly via index.tsx change the prop
url
tosrc
which will be the cached image as database64 string like:Also I have this in use:
Once i use it in the "main" component that is directly called from the
Router > Route
I get theurl
prop and also the src attached from my script. But once I use it in some child components, the url will never rendered.output will be like
origin code to debug like:
I have checked it multiple times, the variable is there to fill the
url
prop and as it works on the "main" component called from the route directly, it should be a Bug, when it is not working on nested components.Your Example Website or App
Steps to Reproduce the Bug or Issue
all described already in "Describe the bug" block
Expected behavior
the
<img/>
tag should be rendered the same way as in the main component.Screenshots or Videos
Does not work in nested Components:
working: direct called component via route:
Platform
Additional context
#2317
EDIT: 2024-10-02 10:36 CEST
Also the Props
data-*="xxx"
will get removes on child components but will in output on "main" component called via route.EDIT 2024-10-02 11:03 CEST
It looks only for custom
<img is="img-cache".../>
to be the problemEDIT: 2024-10-02 12:46 CEST
Add demo app build with sourcemap
demoapp.zip
It looks like in
Profile135415457278656946752.js
it sets the values, but because it is not set viasetAttribute("url", ...
is does not rendering here in the nested component.r.url=e.e=t
would not put the content.But while the other templates are rendered differently when called directly it is only on the nested components.
Update 2024-10-02 13:06 CEST
build without minify enabled:
demoapp2.zip
The text was updated successfully, but these errors were encountered: