Display svg within ionic alert - ionic-framework

I am trying to make custom ionic alerts that include an <svg> in the message parameter since Ionic states that message:
The main message to be displayed in the alert. message can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example <Ionic> would become <Ionic>
However, when I try the following, no image is shown:
const alert = await this.alertController.create({
header: params.title,
message: `
<svg width="27px" height="82px" viewBox="0 0 27 82" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>np_exclamation-mark_920809_FDFF25</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="iPad-Portrait" transform="translate(-371.000000, -1116.000000)" fill-rule="nonzero" fill="#FDFF25">
<g id="np_exclamation-mark_920809_FDFF25" transform="translate(371.000000, 1116.000000)">
<path d="M16.648,63.301 C16.0262694,63.0291894 15.3701293,62.8441243 14.698,62.751 C14.1380094,62.6473705 13.5694896,62.5968131 13,62.6 C12.433,62.6 11.882,62.648 11.351,62.75 C10.677918,62.8431906 10.0207959,63.028248 9.398,63.3 C8.332,63.698 7.367,64.35 6.5,65.25 C4.699,67.081 3.8,69.284 3.8,71.85 C3.8,74.417 4.699,76.6 6.5,78.398 C8.3,80.198 10.465,81.101 13,81.101 C15.566,81.101 17.75,80.198 19.55,78.398 C21.351,76.601 22.25,74.418 22.25,71.851 C22.25,69.284 21.351,67.081 19.55,65.249 C18.683,64.351 17.715,63.699 16.648,63.3 L16.648,63.301 Z M25.898,13.148 C26.933,4.418 22.633,0.082 13,0.148 C3.399,0.183 -0.852,4.448 0.25,12.949 L6.852,58.351 L19.3,58.351 L25.898,13.148 Z" id="Shape"></path>
</g>
</g>
</g>
</svg>`,
buttons: customButtons
});
alert.present();
Here's what it looks like:
When I added the escaped version of the svg, it loaded it as text, rather than an image!

I do not think Ionic alerts support images. You may have to use a Modal or Popover for displaying media. Or maybe change the background using css for the alert and adjust the size and positioning - might get messy. From what I know alerts are not meant to hold images; you could try request it on their Git, maybe they'll form a workaround.

You can use angular to inject a component dynamically into an arbitrary DOM-slot.
Here is an example I have just built to show a countdown next to the dialog buttons:
Wait until your dialog is present and then ....
this.componentInjector.inject(".alert-wrapper .alert-button:nth-child(2)", CountdownComponent, instance => {
instance.text = options.okText;
instance.seconds = options.confirmAfterSeconds;
});
With
#Injectable()
export class ComponentInjector {
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private app: ApplicationRef
) {
}
async inject<T>(slotSelector: string, componentConstructor: new (...args) => T, configureInstance: (instance: T) => any): Promise<void> {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentConstructor);
const slot = document.querySelector(slotSelector);
const ref = componentFactory.create(this.injector, [], slot);
configureInstance(ref.instance as T);
this.app.attachView(ref.hostView);
}
}
It's not polished yet but seems to work.

Related

ionic 5 modal sometimes does not show image

My modal opens and should show a previously selected image. My problem is that only the first time I open it brings up the image The images exist, I analyze them on the console and I see them if I browse them. There is no error here.
The case of upper and lower case I have reviewed it.
the problem is with images, not with text information, the information is perfect.
For some reason, it stops emitting ionImgDidLoad and ionImgWillLoad.
I will appreciate if you can help me, I can not see the error, thank you very much!
ts:
import { ModalExamplePage } from '../modal-Example/modal-Example.page';
…
public info_to_modal = {};
…..
this.info_to_modal = {
photo: this.img_1,
name: this.name
}
I call the modal like this inside an async function:
const modal = await this.modalController.create({
component: ModalExamplePage,
cssClass: 'my-custom-modal-info',
componentProps: {
datainfo: this.info_to_modal
},
});
return await modal.present();
in modal (ts):
#Input() public datainfo;
Then in the html:
<ion-thumbnail slot="start">
<ion-img [src]="datainfo.photo"></ion-img>
</ion-thumbnail>

Custom Components in a Custom Layout in react-admin e.g. appbar, sidebar doesnt' don't show the correct theme colours for all page types

What you were expecting:
When you are dynamically pick a theme object in a custom layout based on the URL/history in react-admin resource, the correct theme is used on the every page type e.g. List, Show, Create and Edit.
What happened instead:
When you go to the resource listing page, the correct theme is used. But when you then navigate to any of the create/show or edit pages, the theme seems to default back to the base / primary one.
Steps to reproduce:
Create Custom Layout file. Overwrite the Appbar and List component (with Listbase) with custom ones too. Although I'm not sure the appbar/listbase steps are necessary.
Use the custom Layout in the Admin component.
Create some resources.
Dynamically pick a theme based on the name of the Resouce (using history).
Navigate to the listing page of the resources. They display the specific theme correctly.
Navigate to the create/show/edit pages of the resources. These, for some reason, default back to the primary theme (or primary default colours).
Related code:
At the root level code..
<Admin
authProvider={AuthProvider({ awsConfig })}
dashboard={Dashboard}
dataProvider={graphQLProvider}
history={history}
layout={Layout}
title="Home"
loginPage={CustomLogin}
// logoutButton={LogoutButton}
>
<LMSResource projection={["details"]} name="Assigment" options={{label: 'Assignments'}} create={AssignmentCreate} list={AssignmentList}
title="Generic" show={AssignmentShow} edit={AssignmentEdit} icon={AssignmentIcon}/>
In the custom Layout file (I have an array of themes to choose from that is imported from another file)
const Layout = ({
children,
dashboard,
logout,
}) => {
const [resource, setResource] = useState('');
const history = useHistory();
useEffect(() => {
const newResource = history.location.pathname.replace(/^\/|\/$/g, '').toLowerCase();
if(newResource===''){
setResource('primary');
} else if (newResource !== resource) {
setResource(newResource);
}
}, [history.location.pathname]);
function getTheme(themes){
let result = ''
var i=0;
for(i = 0; i < themes.length; i++){
if(Object.keys(themes[i])[0] === resource){
result = themes[i][resource];
}
}
return (!result ? themes[0].primary : result );
}
const theme = createMuiTheme(getTheme(themes));
const useStyles = makeStyles(() => ({
...
}));
const classes = useStyles(theme);
const dispatch = useDispatch();
const open = useSelector(state => state.admin.ui.sidebarOpen);
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Grid container>
<Box className={classes.sidebar} color="grey.200" borderRight={1} item md={3} lg={2} component={Grid} display={{ xs: 'none', md: 'block' }}>
<Grid>
<Logo/>
<SchoolText color='textPrimary'/>
</Grid>
<TextField className={[classes.search,classes['search' + resource]]} id="outlined-basic" label="Search" variant="outlined" />
<Sidebar open={open} className={classes.sidebar}>
<Menu logout={logout} hasDashboard={!!dashboard} />
</Sidebar>
</Box>
<Box item component={Grid} xs={12} md={9} lg={10}>
<AppBar title={resource} logout={logout} />
<Box component={Grid} className={classes.breadcrumb} display={{ xs: 'none', md: 'block' }} borderTop={1}>
<Breadcrumbs/>
</Box>
<main>
<div className={classes.content}>
{children}
</div>
</main>
</Box>
<Notification />
</Grid>
</ThemeProvider>
);
}; export default Layout
I can post the List, Show, Create and Edit components if necessary, but I presume if one of resource components is receiving the right theme variables, then they all should?
To be clear, I mean the layout colours outside of the List, Edit, Create and Show components and in the actual Layout components i.e. the appbar background is the wrong colour, as is the sidebar etc. So how can they be right for List but wrong for Edit, Create and Show pages when it uses the same layout component for each in the resource? I don't think I have any way of controlling this?
Environment
React-admin version: 3.7.1
Last version that did not exhibit the issue (if applicable): n/a
React version: 17.0.2
Browser: all
Stack trace (in case of a JS error): n/a
Sooo. Don't mess with Regexs kids, they're dangerous. The issue was related to the different URL structure of create/edit/show vs list and therefore the theme matching didn't work..

Modal for fullsize image with gatsby-image - limit height and width

What I want to achive
I am using gatsby and want to design an image gallery. Clicking on one of the images shall open a modal, which: (1) is showing the image in maximum possible size, so that it still fits into the screen and (2) is centered in the screen.
My Code
/* imagemodal.js */
import React from 'react'
import * as ImagemodalStyles from './imagemodal.module.css'
import { Modal } from 'react-bootstrap'
import Img from 'gatsby-image'
import { useStaticQuery, graphql } from 'gatsby'
export default function Imagemodal() {
const data = useStaticQuery(graphql`
query {
file(relativePath: { eq: "images/mytestimage.jpg" }) {
childImageSharp {
fluid(maxWidth: 1200) {
...GatsbyImageSharpFluid
}
}
}
}
`)
return (
<div>
<Modal
show={true}
centered
className={ImagemodalStyles.imageModal}
dialogClassName={ImagemodalStyles.imageModalDialog}
onHide={(e) => console.log(e)}
>
<Modal.Header closeButton />
<Modal.Body className={ImagemodalStyles.imageModalBody}>
<h1>TestInhalt</h1>
<Img fluid={data.file.childImageSharp.fluid} />
</Modal.Body>
</Modal>
</div>
)
}
/* imagemodal.module.scss */
.imageModalDialog {
display: inline-block;
width: auto;
}
.imageModal {
text-align: center;
}
.imageModalBody img {
max-height: calc(100vh - 225px);
}
The Problem
The image does not scale to the screen size. The image is either too big - so it flows over the vieport - or it is too small. Secondly, the modal size does not respond to the image size correctly and / or is not centered.
What I tried
I used this suggestion for the CSS: How to limit the height of the modal?
I tried as well dozens of other CSS parameter combinations. But I could not find a working solution.
I tried to format the gatsby-image directly with a style-tag.
I tried as well react-modal but had similar problems.
Does anyone have a good solution to show a gatsby-image in full screen size in a responsive modal? For me it is okay to use either the bootstrap-modal or react-modal - or any other suitable solution.
Edit
In the end I ended up with a workaround. I used react-image-lightbox and took the Image-Source from gatsby-image as the input for lightbox. My component gets the data from the graphQL query in the props via props.imageData.
This works quite well for me:
import Lightbox from 'react-image-lightbox';
...
export default function Imagegallery(props) {
...
const allImages = props.imageData.edges
const [indexImageToShow, setIndexImageToShow] = useState()
...
return(
<Lightbox
mainSrc={allImages[indexImageToShow].node.childrenImageSharp[0].fluid.src}
...
/>
Special thanks to #FerranBuireu to point me to the right direction
Assuming that the functionality works as expected, as it seems, it's a matter of CSS rules, not React/Gatsby issue. The following rule:
.imageModalBody img {
max-height: calc(100vh - 225px);
}
It Will never be applied properly, since gatsby-image creates an output of HTML structure of nested <div>, <picture> and <img> so your rule will be affected by the inherited and relativity of the HTML structure. In other words, you are not pointing to the image itself with that rule because of the result HTML structure.
You should point to the <Img>, which indeed, it's a wrapper, not an <img>.
return (
<div>
<Modal show={true} onHide={handleClose} centered className={ImagemodalStyles.imageModal} dialogClassName={ImagemodalStyles.imageModalDialog}>
<Modal.Header closeButton />
<Modal.Body>
<Img className={ImagemodalStyles.imageModalBody} fluid={props.data.file.childImageSharp.fluid} />
</Modal.Body>
</Modal>
</div>
)
The snippet above will add the (spot the difference, without img):
.imageModalBody {
max-height: calc(100vh - 225px);
}
To the wrapper, which may or may not fix the issue, but at least will apply the rule correctly. It's difficult to know what's wrong without a CodeSandbox but you will apply the styles correctly with this workaround.
Keep always in mind that when using gatsby-image, the <img> it's profound in the resultant HTML structure so your styles should apply to the outer wrapper of it.

How to open pdf file into a div or a tab using ionic 3?

How to open pdf file into a div or a tab using ionic 3 ? Using below
code I can open pdf by pdf reader outside from app. I want to show it into a div. Please give me some suggestion.
import { DocumentViewer } from '#ionic-native/document-viewer';
constructor(private document: DocumentViewer) { }
...
const options: DocumentViewerOptions = {
title: 'My PDF'
}
this.document.viewDocument('assets/myFile.pdf', 'application/pdf', options)
You can use a pdf viewer component for Angular 2+ application.
You can write your own or use some available at npm.
Example: https://github.com/VadimDez/ng2-pdf-viewer
Template:
<ion-content>
<pdf-viewer
[src]="pdfSrc"
[render-text]="true"
style="display: block;"
></pdf-viewer>
</ion-content>
component.ts
pdfSrc: string = '/pdf-test.pdf';

Ionicmodal Doesn't Open Until Third Click/Tap

I have set the on-tap value of a div to open a modal which is defined in the page's controller. The div is part of an ng-repeat section. The modal function also accepts some variables passed to it by the div.
When the app is first started on my device (iPhone 6 running iOS 7), I have to tap the div three times before the modal will open. After that, it opens consistently when I tap. But when the app first starts, I have to tap the div 3 times.
There are no errors at all in the console. Once the modal does open, it works as expected.
Any advice?
Here's the code:
HTML
<div on-tap="doModal('{{embed.ID}}','reply','{{embed.oembed}}','{{embed.user}}');">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75 72" width="100" height="50">
<path d="imagestuffhere"/>
</svg>
</div>
CONTROLLER
$scope.doModal = function(this_ID,modaltype,this_oembed,this_user) {
$scope.contact = {
name: this_ID,
info: modaltype,
oembed: this_oembed,
user: this_user
}
if (modaltype == 'repost') {
$scope.modaltempl = 'templates/repost-modal.html';
}
else if (modaltype == 'reply') {
$scope.modaltempl = 'templates/reply-modal.html';
}
else if (modaltype == 'like') {
$scope.modaltempl = 'templates/like-modal.html';
}
else {
$scope.modaltempl = 'templates/like-modal.html';
}
$ionicModal.fromTemplateUrl($scope.modaltempl, {
scope: $scope,
animation: 'slide-in-up'
}).then(function (modal) {
$scope.modal = modal;
$scope.modal.show();
console.log($scope.modaltempl);
});
};
$scope.closeModal = function() {
$scope.modal.hide();
};
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
I've tried pulling the $ionicModal.fromTemplateUrl($scope.modaltempl, bit outside of $scope.doModal and calling $scope.modal.show from within $scope.doModal, but the result is the same.
It definitely gets to the scope.modal.show(); statement even when the modal does not open, because the console.log I've included just after it gets output.
Before I had added the svg to the interface, I was testing this using a button element and had the same issue. It also had the same issue when I used ng-click instead of on-tap.
Thanks for any help!
Turns out the issue was not in the Ionic controller code nor the triggering html, but in the modal template, itself.
Per the Ionic documentation, I had each of my modal templates wrapped in this:
<script type="text/ng-template" id="repost-modal.html"></script>
By removing that and replacing it with just <ion-modal-view></ion-modal-view> the issue was resolved and the modals now open very nicely on the first click.