Reputation: 145
I am developing a pdf download form from a drupal api, the pdfs are mapped within the options of a select, when I select a pdf when I hit the download button it has to open the link where the pdf is located and from there it can be downloaded. I picked up the value of the selected option and put a tag to redirect the page to the address where the pdf is, but it does not let me use the href, it gives me the following error: The expected type comes from property 'href' which is declared here on type 'DetailedHTMLProps<AnchorHTMLAttributes, HTMLAnchorElement>', how can I fix this error. Or maybe there is another way to do it without the href?
import React from 'react'
import { forwardRef, AnchorHTMLAttributes, HTMLAttributes} from 'react'
import { useState, useEffect, useRef } from 'react'
import { getDocument } from '../../api/drupalAPI'
import { Document } from '@icofcv/common';
type AnchorProps = AnchorHTMLAttributes<HTMLAnchorElement>
export function Manuals () {
const [documents, setDocuments] = useState<Document[]>([]);
const [inputValue, setInputValue] = useState("")
const ref = useRef<HTMLAnchorElement>(null)
const [isLoading, setIsLoading] = useState (false)
const fetchDocuments = async () => {
setIsLoading(true)
getDocument().then((response) => {
console.log(response)
setDocuments(response);
setIsLoading(false)
}).catch((error) => {
console.error(error);
throw error;
});
}
useEffect(() => {
fetchDocuments();
}, []);
return(
<>
<div className="card bg-white px-2 py-3 md:p-6">
<h1 className="pb-3 font-medium">Manuales de Estándares</h1>
<div className="card-body py-2 md:px-12 mx-auto w-100">
<p className="text-neutral-600 text-sm mb-2">Manual de estándares de la práctica de la Fisioterapia en Centros Sanitarios</p>
<button className="btn bg-teal-600 hover:bg-teal-700 text-white px-8 w-40" type="button">Descargar</button>
<p className="text-neutral-600 text-sm font-bold my-2">Desde el siguiente formulario podrá descargar los anexos del manual, se han clasificado en 2 grupos para una mejor búsqueda.</p>
<div className="flex flex-col md:flex-row items-end justify-between my-4">
<div className="relative z-0 w-full group">
<label className="block text-sm font-medium text-gray-900 mb-2">Anexos Estándares*</label>
<select onChange={(e) => setInputValue(e.target.value)} id="" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option selected>Seleccione Anexo I</option>
{documents.map(docu => (
<>
<option key={docu.id} selected>{docu.contentUrl}</option>
</>
))}
</select>
</div>
<a ref={ref} href={(e: React.FormEvent<HTMLInputElement>) => { const newValue = e.currentTarget.value;setInputValue(newValue)}}></a>
</div>
<div className="flex flex-col md:flex-row items-end justify-between my-4">
<div className="relative z-0 w-full group">
<label className="block text-sm font-medium text-gray-900 mb-2">Anexos Estándares*</label>
<select id="" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option selected>Seleccione Anexo II</option>
</select>
</div>
<button className="btn bg-teal-600 hover:bg-teal-700 text-white px-8 ml-4 w-full md:w-40 my-2 md:my-0" type="button">Descargar</button>
</div>
<div className="flex flex-col md:flex-row items-end justify-between my-4">
<div className="relative z-0 w-full group">
<label className="block text-sm font-medium text-gray-900 mb-2">Anexos Estándares*</label>
<select id="" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option selected>Seleccione Anexo III</option>
</select>
</div>
<button className="btn bg-teal-600 hover:bg-teal-700 text-white px-8 ml-4 w-full md:w-40 my-2 md:my-0" type="button">Descargar</button>
</div>
</div>
</div>
</>
)
}
Upvotes: 2
Views: 8131
Reputation: 42160
An <a>
element is a link and the href
is the string
of the URL that you are linking to. An href
cannot be a function. If you need a function, you can use a different prop such as onClick
.
when I select a pdf when I hit the download button it has to open the link where the pdf is located and from there it can be downloaded. I picked up the value of the selected option and put a tag to redirect the page to the address where the pdf is
It looks like you are trying to have a "Descargar" ("Download") button that will the open the currently selected PDF URL in a new window.
You don't need refs for this because you already have the selected document URL in your inputValue
state.
onClick
One way to set this up is to use an onClick
handler of the <button>
which can execute any code that you want. You can call window.open()
and use "_blank"
to open in a new window. We can disable the button if no document has been selected.
<div>
<div>
<label htmlFor="anexo-i">
Anexos Estándares*
</label>
<select
onChange={(e) => setInputValue(e.target.value)}
value={inputValue}
name="anexo-i"
id="anexo-i"
>
<option value="">Seleccione Anexo I</option>
{documents.map((docu) => (
<option key={docu.id} value={docu.contentUrl}>
{docu.name}
</option>
))}
</select>
</div>
<button
type="button"
disabled={!inputValue}
onClick={() => window.open(inputValue, '_blank')}
>
Descargar
</button>
</div>
href
You can use an <a>
element to handle the downloading. You could open the PDF in a new window with target="_blank"
but you can also make use of the download
attribute of the <a>
element.
An <a>
element can also have an onClick
handler to execute any code. You can call e.preventDefault()
in your custom code to prevent navigating to the URL and use your own handling instead. Here I am using the onClick
to handle the "disabled" behavior. You'll probably want to change the styling when it is disabled as well, since the <a>
does not have the same built-in disabled behavior as the <button>
.
<div>
<div>
<label htmlFor="anexo-i">
Anexos Estándares*
</label>
<select
onChange={(e) => setInputValue(e.target.value)}
value={inputValue}
name="anexo-i"
id="anexo-i"
>
<option value="">Seleccione Anexo I</option>
{documents.map((docu) => (
<option key={docu.id} value={docu.contentUrl}>
{docu.name}
</option>
))}
</select>
</div>
<a
className={
inputValue ? "your regular styles" : "your disabled styles"
}
role="button"
href={inputValue}
target="_blank"
onClick={(e) => {
if (!inputValue) {
e.preventDefault();
alert("Please select a file");
}
// otherwise, do the default behavior
}}
>
Descargar
</a>
</div>
CodeSandbox with both approches.
Upvotes: 3