Baseado na solução absolutamente brilhante @claviska, a quem todo o crédito é devido.
Entrada de arquivo Bootstrap 4 com todos os recursos com validação e texto de ajuda.
Com base no exemplo do grupo de entrada , temos um campo de texto de entrada fictício usado para exibir o nome do arquivo para o usuário, que é preenchido a partir do onchange
evento no campo real do arquivo de entrada escondido atrás do botão de rótulo. Além de incluir o suporte à validação do bootstrap 4 , também foi possível clicar em qualquer lugar da entrada para abrir a caixa de diálogo do arquivo.
Três estados da entrada do arquivo
Os três estados possíveis são não validados, válidos e inválidos com o required
conjunto de atributos da marca de entrada html dummy .
Marcação HTML para a entrada
Introduzimos apenas duas classes personalizadas input-file-dummy
e input-file-btn
modelamos e conectamos adequadamente o comportamento desejado. Tudo o resto é a marcação padrão do Bootstrap 4.
<div class="input-group">
<input type="text" class="form-control input-file-dummy" placeholder="Choose file" aria-describedby="fileHelp" required>
<div class="valid-feedback order-last">File is valid</div>
<div class="invalid-feedback order-last">File is required</div>
<label class="input-group-append mb-0">
<span class="btn btn-primary input-file-btn">
Browse… <input type="file" hidden>
</span>
</label>
</div>
<small id="fileHelp" class="form-text text-muted">Choose any file you like</small>
Disposições comportamentais JavaScript
A entrada fictícia precisa ser apenas de leitura, conforme o exemplo original, para impedir que o usuário altere a entrada que só pode ser alterada através da caixa de diálogo de arquivo aberto. Infelizmente, a validação não ocorre nos readonly
campos, portanto, alternamos a editabilidade da entrada em foco e desfoque ( eventos jquery onfocusin
e onfocusout
) e garantimos que ela se torne validável novamente quando um arquivo for selecionado.
Além de tornar o campo de texto clicável, acionando o evento de clique do botão, o restante da funcionalidade de preenchimento do campo fictício foi visualizado por @claviska.
$(function () {
$('.input-file-dummy').each(function () {
$($(this).parent().find('.input-file-btn input')).on('change', {dummy: this}, function(ev) {
$(ev.data.dummy)
.val($(this).val().replace(/\\/g, '/').replace(/.*\//, ''))
.trigger('focusout');
});
$(this).on('focusin', function () {
$(this).attr('readonly', '');
}).on('focusout', function () {
$(this).removeAttr('readonly');
}).on('click', function () {
$(this).parent().find('.input-file-btn').click();
});
});
});
Ajustes de estilo personalizado
Mais importante ainda, não queremos que o readonly
campo pule entre fundo cinza e branco, para garantir que ele permaneça branco. O botão span não possui um cursor de ponteiro, mas precisamos adicionar um para a entrada de qualquer maneira.
.input-file-dummy, .input-file-btn {
cursor: pointer;
}
.input-file-dummy[readonly] {
background-color: white;
}
nJoy!