react native: How to set Image defaultSource on Android.
I have read the React native 1.58 document. I found the Image props defaultSource supported iOS only.
I need to set the default Image when the network Image load error.
I used to write the code like this:
{ ImageUrl?
<Image style={styles.docimg}
source={{uri: ImageUrl}}/>
:
<Image style={styles.docimg}
source={require('../../../resource/default.png')}/>
}
Now there is a problem. When the URL is a string type, but it isn't a correct network Image. As the URL is true then the Image will show nothing.
I saw the Image props onError maybe solve my issue.
I need to set the placeholder Image.
I have tried using #Ravi Raj's answer but seems not related to failure on loading image.
Beside the answer will make the image keep flashing between the default and actual image. ( The error that #vzhen met )
Therefore I have developed based on his answer and generated this component. See if this suits you ;)
progressive-image.js - Component <ProgressiveImage/>
import React, { Component } from 'react';
import { Image } from 'react-native';
export default class ProgressiveImage extends Component {
state = { showDefault: true, error: false };
render() {
var image = this.state.showDefault ? require('loading.png') : ( this.state.error ? require('error.png') : { uri: this.props.uri } );
return (
<Image style={this.props.style}
source={image}
onLoadEnd={() => this.setState({showDefault: false})}
onError={() => this.setState({error: true})}
resizeMode={this.props.resizeMode}/>
);
}
}
Then import and call the component like this:
import ProgressiveImage from './progressive-image';
<ProgressiveImage style={{width: 100, height: 100}}
uri={'http://abc.def/ghi.jpg'}
resizeMode='contain'/>
Hope this answer can help you ;)
You just try this and hope it works...
// initially showDefault will be false
var icon = this.state.showDefault ? require('../../../resource/default.png') : {uri: ImageUrl};
return(
<Image
style={styles.docimg}
source={icon}
onLoadStart={() => this.setState({showDefault: true})}
onLoad={() => this.setState({showDefault: false})}
/>
)
Setting showDefault = false in onLoad() should not trigger url
fetch again since images are cached by default in android and IOS.
Work for me
<ImageBackground
style={{
width: 100,
height: 100,
marginRight: 20,
borderRadius: 10,
}}
source={
require('../../assets/images/Spinner.gif') //Indicator
}>
<Image
style={{
width: 100,
height: 100,
marginRight: 20,
borderRadius: 10,
}}
source={{
uri: `//Image U want To Show`
}}
/>
</ImageBackground>
const [error, setError]=setState(false);
return(){
<Image
onError={(error) => {
setError(true);
}}
source={
error
? require("../../assets/images/defaultImage.png")
: { uri: imageUrl }
}
/>
}
This will show the default image if your network image fails to load or gives an error 404.
According to the docs, the defaultSource prop is ignored on Android on Debug builds, so if you are looking for a placeholder while the actual source is loading -- not in case of errors -- make sure to test on release mode before implementing workarounds to load it only because of debug mode.
"Note: On Android, the default source prop is ignored on debug builds."
defaultSource doesn't work on android...
Please follow the method bellow to fix it:
Dont forget to import View, ImageBackground, & Image
class MyComponent extends Component {
constructor() {
this.state = {
isImageLoading: true,
}
}
render() {
<View>
<ImageBackground
source={{ uri: this.state.isImageLoading ? YOUR_DEFAULT_IMAGE : null }}
>
<Image
source={{ uri: YOUR_IMAGE }}
onLoad={() => this.setState({ isImageLoading: false })}
/>
</ImageBackground>
</View>
}
}
Related
I am trying to navigate to a nested stack, when I use navigation.push(AppRoutes.RescueMeLanding.Name) I get the error:
Couldn't find a 'component', 'getComponent' or 'children' prop for the screen 'RescueMeStackScreen'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.
Any ideas?
const AppRoutes = {
....
RescueMeLanding: {
Name: 'RescueMeStackScreen',
Label: 'Rescue Me',
isProtected: true,
},
....
};
RescueMeStackScreen:
const RescueMeStackScreen = () => {
return (
<RescueMeStack.Navigator
initialRouteName={AppRoutes.RescueMeLanding.Name}
>
<RescueMeStack.Screen
name={AppRoutes.RescueMeLanding.Name}
component={RescueMeLandingScreen}
options={{ headerShown: false }}
/>
<RescueMeStack.Screen
name={AppRoutes.RescueMeMap.Name}
component={RescueMeScreen}
options={{ headerShown: false }}
/>
;
</RescueMeStack.Navigator>
);
RootStackNavigator:
const RootStackNavigator = () => {
return (
<RootStack.Navigator
initialRouteName={AppRoutes.LoginRegistration.Name}
mode="modal"
>
....
<RootStack.Screen
name={AppRoutes.RescueMeLanding.Name}
component={RescueMeStackScreen}
options={{
title: AppRoutes.Register.Label,
headerShown: false,
animationEnabled: false,
}}
/>
....
</RootStack.Navigator>
);
When navigating to nested component, you need to specify parent explicitly.
See this for further information.
Thus, in your case;
navigation.push(AppRoutes.RescueMeLanding, { screen: AppRoutes.RescueMeLanding.Name })
What I also would suggest is name stack differently than the screen. Such as;
navigation.push(AppRoutes.RescueMeLandingStack, { screen: AppRoutes.RescueMeLanding.Name })
I installed Ant Design with npm install antd, and mounted the Switch component.
My component is:
import React, { useState } from 'react';
import { Switch } from 'antd';
const FullWidthToggle = (isEnabled) => {
const [isChecked, setIsChecked] = useState(isEnabled);
const onChange = (isChecked) => {
setIsChecked(!isChecked)
}
return (
<div className='full-width-toggle'>
<p> <strong>{isChecked ? 'enabled' : 'disabled'}</strong> </p>
<Switch onChange={onChange}/>
</div>
)
}
export default FullWidthToggle;
Any time I switch, the toggle and the text changes, but I get this error in the console:
Uncaught RangeError: Maximum call stack size exceeded at wrapperRaf
I get the same error with the Collapse component, and I suppose with every animation.
I suspect I need to install or configure something else, can someone tell me what?
I found the answer in the meantime here:
https://github.com/vueComponent/ant-design-vue/issues/1219
I had to add
resolve: {
...
alias: {
...
raf: 'node_modules/raf/',
},
},
to my webpack.config.js file
I am trying to install mdbootstrap vue into a Laravel 5.7 project, but i realy don't understand how i suppose to do it.
I did everything like in here but anyway it doesn't work.
On rendering I got such vue error :
Unknown custom element: <mdb-btn> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Code from view:
<mdb-btn color="elegant">Elegant</mdb-btn>
please follow this steps from this answer https://github.com/mdbootstrap/Vue-Bootstrap-with-Material-Design/issues/1#issuecomment-372342369 :
insert this in your main.js file:
import 'mdbvue/build/css/mdb.css'
import 'mdbvue/src/components/Waves.css'
then in your component import the components that you need:
import { Container, Row, Column, Btn, Card } from 'mdbvue';
for example:
<template>
<mdb-btn-fixed #mouseenter.native="hover" #mouseleave.native="hoverOut"
icon="pencil" size="lg" :bottom="30" :right="25">
<mdb-btn-fixed-item :show="show" color="red" icon="star"/>
<mdb-btn-fixed-item :show="show" color="yellow" icon="user"/>
<mdb-btn-fixed-item :show="show" color="green" icon="envelope"/>
<mdb-btn-fixed-item :show="show" color="blue" icon="shopping-cart"/>
</mdb-btn-fixed>
</template>
<script>
import { mdbBtn, mdbBtnFixed, mdbBtnFixedItem } from 'mdbvue';
export default {
data() {
return {
show: false
};
},
name: 'ButtonPage',
components: {
mdbBtn,
mdbBtnFixed,
mdbBtnFixedItem
},
};
You have a lot of examples of usage here at the bottom: https://mdbootstrap.com/docs/vue/components/buttons/
I am using NativeScript Angular2 and on my page, I have added a ListPicker for user to select an option. The following is the code snippet for the html file:
<ListPicker #languagePicker id="languagePicker" [visibility]="langSelectStatus()" [items]="languages" class="mek-select-field" (selectedIndexChange)="selectedIndexChanged(languagePicker)"
>
</ListPicker>
The following is the css:
.mek-select-field {
height: 70px;
border-color: lightblue;
border-width: 1px;
margin: 0;
}
I found the code runs without any issues on iOS, the following is the screenshot:
ListPicker on iOS
However, on Android, found that the ListPicker was not working. It display the list, but cannot scroll between the options defined. The following is the screenshot:
ListPicker on Android
The following is the environment info:
NativeScript version: 2.4.0
NativeScript-Angular version: 1.1.3
NativeScript Android Runtime version: 2.4.1
Android emulator: API 25 Nexus 6
I am new to NativeScript and not sure if it's related to my environment or not.
Any advice will be much welcome.
Thanks in advance
[Updated on 2016 Nov 26]:
By exploring the sample as advised by Niko and more testing, I found that the behavior only appears when the option values are fetch from a backend via Http service. For example, in the example's creating-listpicker.component.ts class, if I change the option list to retrieve from Http backend like below code:
export class CreatingListPickerComponent {
public pokemons: Array<string>;
public picked: string;
constructor(private http: Http) {
this.pokemons = [];
this.http.get('http://192.168.31.120:3000/pokemons').subscribe(
res => {
let list = res.json();
console.log(`Pokemon list: ${list}`);
for (var i = 0; i < list.length; i++) {
this.pokemons.push(pokemonList[i]);
}
}
);
/* for (var i = 0; i < pokemonList.length; i++) {
this.pokemons.push(pokemonList[i]);
}*/
}
public selectedIndexChanged(picker) {
console.log('picker selection: ' + picker.selectedIndex);
this.picked = this.pokemons[picker.selectedIndex];
}
}
Where the endpoint will response with the exact same value as the hardcoded value. When I run the above code in Android (both emulator and device), I found that the ListPicker will not able to show any options (or only the first) option from time to time. It's very easy to re-produce. iOS don't have this problem.
I believe there exist some issues when the options for ListPicker is coming from a Http backend, where some delay will be present.
Kindly advice
Clarence
To be able to add ListPicker items after your HTTP request you should create new array after receiving the data and to make the old array to point to the new one. You could review the below-attached sample.
HTML
<FlexboxLayout flexDirection="column" exampleTitle toggleNavButton>
<Label class="h3 p-15 text-left" text="Pick a pokemon" textWrap="true"></Label>
<!-- >> creating-listpicker-html -->
<ListPicker #picker id="pickerid" class="p-15"
[items]="pokemons"
[selectedIndex]="selectedIndex"
(selectedIndexChange)="selectedIndexChanged(picker)">
</ListPicker>
<!-- << creating-listpicker-html -->
<Label [text]="'Selected pokemon: ' + picked" class="p-15" textWrap="true"></Label>
</FlexboxLayout>
TypeScript
import { Component , NgZone} from "#angular/core";
import { getFile, getImage, getJSON, getString, request } from "http";
var pokemonList = ["Bulbasaur", "Parasect", "Venonat", "Venomoth", "Diglett",
"Dugtrio", "Meowth", "Persian", "Psyduck", "Arcanine", "Poliwrath", "Machoke"];
#Component({
selector: "creating-listpicker",
templateUrl: "ui-category/listpicker/creating-listpicker/creating-listpicker.component.html"
})
export class CreatingListPickerComponent {
public pokemons: Array<string>;
public picked: string;
constructor(private zone:NgZone) {
this.pokemons = [];
}
ngOnInit(){
var that =this;
getJSON("https://httpbin.org/get?item1=item1&item2=item2&item3=item3")
.then((r) => {
console.log((<any>r).args.item1);
let args = (<any>r).args;
var arr = [args.item1, args.item2, args.item3]
this.pokemons = arr;
}, (e) => {
alert("GetJSON: " + e)
});
}
public selectedIndexChanged(picker) {
console.log('picker selection: ' + picker.selectedIndex);
this.picked = this.pokemons[picker.selectedIndex];
}
}
I'm trying to trigger an animation on an hidden element of a child component. To be simple, the animation should occur when the element appears, and then each time a user click on a button from the parent component.
Here is simple code :
(tried to plunkr it, but impossible to import trigger component from angular core)
app.ts
import {ChildComponent} from './child';
#Component({
selector: 'my-app',
template: `
<button id="showChildButton" (click)="setShowChild()">Show Child</button>
<button id="triggerAnimation">Trigger animation</button>
<child-component *ngIf="showChild"></child-component>
`
.....
})
export class App {
showChild: boolean = false;
setShowChild() {
this.showChild = true;
}
}
child.ts
import {
Component,
trigger,
state,
style,
transition,
animate
} from '#angular/core'
#Component({
selector: 'child-component',
template: `<h1 [#inflateIn]>Hello</h1>`,
animations: [
trigger('inflateIn', [
transition('void => *', [
animate(100, style({ transform: 'scale(1.1)'}))
]),
transition('* => *', [
animate(100, style({ transform: 'scale(1.1)'}))
])
])
]
})
export class ChildComponent {
}
I am able to animate the , the first time it appears, but I can't figure out how to trigger this animation again, when clicking on button #triggerAnimation of the parent component.
I searched for examples but I didn't find anything that solve my case.
Thanks for your help
You have to toggle the showChild variable. You can change your setShowChild() method as follows
setShowChild() {
this.showChild === false ? true : false;
}
It checks if this.showChild is false so make it true otherwise false to hide it again.
I hope this is what you wanted to get the desired result?