Skip to content
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

[Android] Opening local HTML file as text #428

Closed
filiptdz opened this issue Mar 18, 2019 · 59 comments
Closed

[Android] Opening local HTML file as text #428

filiptdz opened this issue Mar 18, 2019 · 59 comments
Labels

Comments

@filiptdz
Copy link

filiptdz commented Mar 18, 2019

When I use source={require('./filePath.html')}, the iOS WebView loads the file correctly, but Android renders it as text instead:

WhatsApp Image 2019-03-18 at 11 15 59

@ateymoori
Copy link

same problem

@maxschmeling
Copy link
Contributor

I'm having an issue on Android also, but it's actually crashing with this error:
TypeError: source is not an Object. (evaluating "method' in source')

It is working if I use a URI source to a local asset (which is what I do when __DEV__ isn't truthy) but this breaks dev reloading:
{ uri: "file:///android_asset/overlay.html" }

@sunkaigoon
Copy link

sunkaigoon commented Apr 9, 2019

same problem with Android
render() {
let html = require('./tpl.html');
if (!__DEV__ && global.ANDROID) {
html = { uri: 'file:///android_asset/tpl.html' };
}
return (
<WebView
ref={(ref) => { this.chart = ref; }}
javaScriptEnabled
scrollEnabled={false}
injectedJavaScript={renderChart(this.props)}
style={{
flex: 1,
backgroundColor: this.props.backgroundColor || 'transparent'
}}
originWhitelist={['*']}
source={html}
onMessage={event =>
(this.props.onPress ? this.props.onPress(JSON.parse(event.nativeEvent.data)) : null)}
/>
);
}
When __DEV__ crashing with this error:
TypeError: source is not an Object. (evaluating "method' in source'),
but When !__DEV__ it get a blank view

@tusharmutreja
Copy link

same error , Opening html file as text in IOS. Any updates???

@filiptdz
Copy link
Author

@tusharmutreja wait, this is happening to you on iOS? Care to show your code?

@danielgindi
Copy link

danielgindi commented Apr 25, 2019

Does not happen in iOS, happens in Android as no Content-Type header is returned for the asset.
I think this is only in Debug mode though.

@SnaiNeR
Copy link

SnaiNeR commented Apr 27, 2019

Error

TypeError: TypeError: TypeError: source is not an Object. (evaluating ''method' in source')

with local file in source prop
source={require('../index.html')}

But works correctly with url in source prop
source={{uri: 'mysite' }}

Android Debug

@filiptdz
Copy link
Author

Does not happen in iOS, happens in Android as no Content-Type header is returned for the asset.
I think this is only in Debug mode though.

@danielgindi I found this in my investigation as well, but either that isn't the only problem, or I wasn't successful in adding the Content-Type

@RBrNx
Copy link

RBrNx commented Jun 14, 2019

Currently having the same issue with Expo SDK 33 as they have now added support for this package. Did anyone find a proper solution for Dev + Prod?

@reggie3
Copy link

reggie3 commented Jun 23, 2019

@filiptdz How did you attempt to set the Content-Type header?

@filiptdz
Copy link
Author

filiptdz commented Jun 23, 2019 via email

@reggie3
Copy link

reggie3 commented Jun 25, 2019

@filiptdz Do you mind saying what you did and how you did it?

@filiptdz
Copy link
Author

@reggie3 I'm sorry, but it's been a couple months. My best guess would be adding it on the WebView createViewInstance method on /android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java

@smontlouis
Copy link

I fixed the issue by doing the following:

  • Create an js file with export default 'your html file in string'
  • <WebView source={{ html: require('./html.js') }} />

@danielgindi
Copy link

I fixed the issue by doing the following:

  • Create an js file with export default 'your html file in string'
  • <WebView source={{ html: require('./html.js') }} />

This does not fix the issue, as it will not load any resources referenced by the HTML.

@smontlouis
Copy link

Actually yes it will. Since the html will be processed like an html file. I am just changing the way its imported. I am using webpack and preact with some loaders to generate my html. Everything is working flawlessly.

@danielgindi
Copy link

You're not getting it. It you have an assets folder with assets/index.html + assets/logo.png, then index.html won't be able to reference the logo.png. It could reference external resources, but for local resources - you would have to modify the HTML and change the urls of the resources.
I'm guessing those urls are also different between dev and prod.

@smontlouis
Copy link

smontlouis commented Jun 28, 2019

Oh this is what you mean. Ok but this is not really an issue, it makes sense.

Sorry I was talking about the first issue.

If you want to use local assets you need to bundle them inline using webpack or host them externally.

@danielgindi
Copy link

Well that defeats the purpose of the property that's meant to load an HTML from the assets folder :-)

@PaddyLock
Copy link

If it helps anyone, I resorted to hosting my html file in an S3 bucket and including using

source={{uri: 'https://mys3bucket.s3-eu-west-1.amazonaws.com/mobile_assets/myfile.html'}}

@paldepind
Copy link

paldepind commented Jul 10, 2019

Per this comment it appears that source={require('./filePath.html')} is not supported by react-native-webview.

@dellwatson
Copy link

dellwatson commented Jul 15, 2019

anyone fix this on Android ? need this urgent.

I can't even path the file in android, this path didnt work { uri: "file:///android_asset/index.html" }

@filiptdz
Copy link
Author

filiptdz commented Jul 17, 2019 via email

@paldepind
Copy link

paldepind commented Jul 30, 2019

@dellwatson This workaround may help. That's what we did to get around this issue. It's essentially what @bulby97 suggested above but with a Webpack configuration that bundles everything into a single HTML file to fix the problem pointed out by @danielgindi.

@filiptdz
Copy link
Author

@paldepind nice one! thanks for sharing

@Satish1729
Copy link

Error

TypeError: TypeError: TypeError: source is not an Object. (evaluating ''method' in source')

with local file in source prop
source={require('../index.html')}

But works correctly with url in source prop
source={{uri: 'mysite' }}

Android Debug

Any fix for this issue? Appreciate the help

@github-actions github-actions bot added the Stale label Jan 3, 2020
@filiptdz
Copy link
Author

filiptdz commented Jan 3, 2020 via email

@assetcorp
Copy link

It seems there are many things that need to be looked into in order to solve this issue. It would be a dream come true if it's resolved though. :)

@khurana3192
Copy link

still searching for solutions

@jamonholmgren
Copy link
Member

@danielgindi I appreciate your detailed comment from last September. Have you learned any more about this in the meantime?

@github-actions github-actions bot closed this as completed Jun 5, 2020
@samithaf
Copy link

The following solution works in both iOS and Android Apps. Also I have tested it on Debug and Release builds.

Web view component:

<WebView
        ref={webView}
        source={{html: require('./chart-template').template()}}
        showsHorizontalScrollIndicator={false}
        bounces={false}
        scrollEnabled={false}
      />

chart template file:

export const template = () => `<!doctype html>

<html lang="en">
<head>
  <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'/>
</head>

<body>
  <h1>Hey React Native</h1>
</body>
</html>`

@jamonholmgren
Copy link
Member

Very interesting, @samithaf !

@jtreat3
Copy link

jtreat3 commented Jul 22, 2020

And if that html template references JS scripts, or images?
Doesn't work for me.

@jtreat3
Copy link

jtreat3 commented Sep 9, 2020 via email

@samithaf
Copy link

samithaf commented Sep 9, 2020

@jtreat3 I used this solution to wire up a charting library which had a JS script and it was working. I can tryout again if you can specify the build type that you noticed the problem

Here is a sample working solution which got JS and CSS in the HTML file, https://snack.expo.io/@samithaf/react-native-web-view

@jtreat3
Copy link

jtreat3 commented Sep 10, 2020 via email

@samithaf
Copy link

I was able to apply CSS with an inline style tag, but I wasn't able to execute JS, inline or otherwise.

On Wed, Sep 9, 2020 at 7:07 PM Samitha Fernando @.***> wrote: @jtreat3 https://github.com/jtreat3 I used this solution to wire up a charting library which had a JS script and it was working. I can tryout again if you can specify the build type that you noticed the problem — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#428 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEN5EZU4CE2TZZGN7KUQR3LSFADELANCNFSM4G7HSZHQ .
-- Jay Treat

If you looked at the sample project that I have shared, for sure it execute the JS and draws the chart as well.

@jeloagnasin
Copy link

@samithaf, your solution worked! But I had to add String.raw to escape all characters.

@jtreat3, you might want to try adding String.raw at the start of your HTML content like below.

export const template = () => String.raw`<!doctype html>

<html lang="en">
<head>
  <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'/>
</head>

<body>
  <h1>Hey React Native</h1>
</body>
</html>`

@samithaf
Copy link

samithaf commented Oct 4, 2020

@jeloagnasin Good to hear that the solution worked for you. Maybe the solution can be added to readme.md since it looks so many people stuck with the same problem.

@Alain1405
Copy link

@jtreat3 I used this solution to wire up a charting library which had a JS script and it was working. I can tryout again if you can specify the build type that you noticed the problem

Here is a sample working solution which got JS and CSS in the HTML file, https://snack.expo.io/@samithaf/react-native-web-view

@samithaf as your solution anything to do with TradingView? I am currently investigating the best way to support loading TV files from local files on Android.

@samithaf
Copy link

@Alain1405 I found this workaround when I wanted to show the high-charts in a simple web-view within React Native. Probably you can apply the sample principal to TradingView too?

@prasanna-ML-expert
Copy link

@samithaf, your solution worked! But I had to add String.raw to escape all characters.

@jtreat3, you might want to try adding String.raw at the start of your HTML content like below.

export const template = () => String.raw`<!doctype html>

<html lang="en">
<head>
  <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'/>
</head>

<body>
  <h1>Hey React Native</h1>
</body>
</html>`

Did your html had div tags and js files and script tags? Only static part of html file worked for me, but not dynamic javascript code.

@samithaf
Copy link

@jkreddy123 could you please check the following working sample? (this one creates a chart on run time) https://snack.expo.io/@samithaf/react-native-web-view

@dpwiese
Copy link

dpwiese commented Jan 24, 2021

The following solution works in both iOS and Android Apps. Also I have tested it on Debug and Release builds.

@samithaf your solution is quite nice, although using strings of html and JavaScript becomes a problem when the JS itself contains functions which use template literals. Have you encountered the same or figured out a solution for this case?

@Shishir-Tiwari
Copy link

The following solution works in both iOS and Android Apps. Also I have tested it on Debug and Release builds.

@samithaf your solution is quite nice, although using strings of html and JavaScript becomes a problem when the JS itself contains functions which use template literals. Have you encountered the same or figured out a solution for this case?

Hi @dpwiese , we could preserve functions by using a custom replacer.

const stringifyWithFunctions = (options): string => {
      const functions =  {};
      let serializedOptions: string;
      let i = 0;

      serializedOptions = JSON.stringify(options, (val, key) => {
        const fcId = `###Function${i}###`;

        // set reference to function for the later replacement
        if (typeof key === 'function') {
          functions[fcId] = key.toString();
          i += 1;
          return fcId;
        }

        return key;
      });

      // replace ids with functions.
        Object.keys(functions).forEach(key => {
          serializedOptions = serializedOptions.replace(`"${key}"`, functions[key]);
        });

      return serializedOptions;
    };

Updated version of @samithaf 's example.
https://snack.expo.io/ccYbFcyT7

@Corrob
Copy link

Corrob commented Aug 12, 2022

In case anyone else is looking for a different solution here, this is what worked for me: https://medium.com/@snehabagri.90/reactnative-webview-with-local-content-c98a09340801

It is essentially just adding the HTML, JS, and CSS files to android assets and the iOS IPA and then using a local file URI to show it.

@mihkuno
Copy link

mihkuno commented Dec 31, 2022

I got this to work on expo, ios, android somehow

https://stackoverflow.com/a/74966760/12724665

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests