Come posso cambiare angolarjs ng-src quando API restituisce valore nullo?
-
20-12-2019 - |
Domanda
Nel lavorare con l'API da themoviedb.com, sto avendo il tipo utente in un campo di input, invio della richiesta API su ogni tastiera. Nel testare questo, a volte il poster del film sarebbe "nullo" invece del poster_path previsto. Preferisco default per un'immagine segnaposto per indicare che un poster non è stato trovato con la richiesta API.
Quindi, poiché l'intero URL poster_path non è offerto dall'API, e dal momento che sto usando un AngularJS NG-REPEAT, devo strutturare il tag immagine come SO (usando i dati fittizi per salvare su spazio): Ma poi la console mi dà un errore a causa di una cattiva richiesta poiché un percorso completo dell'immagine non viene restituito. Ho provato a utilizzare o prompt:
{{'http://example.com/'+movie.poster_path || 'http://example.com/missing.jpg'}}
.
Ma questo non funziona in questo caso. Quindi ora con il JavaScript. Non riesco a ottenere la fonte di immagine usando GetElementsBytagname o GeetELementByClass, e usare GetElementByID sembra solo afferrare la prima ripetizione e nient'altro che ho pensato sarebbe il caso. Ma anche allora non riesco a sostituire la fonte dell'immagine. Ecco la struttura del codice che ho tentato:
<input type="text" id="search">
<section ng-controller="movieSearch">
<article ng-repeat="movie in movies">
<img id="myImage" src="{{'http://example.com/'+movie.poster_path}}" alt="">
</article>
</section>
<script>
function movieSearch($scope, $http){
var string,
replaced,
imgSrc,
ext,
missing;
$(document).on('keyup', function(){
string = document.getElementById('search').value.toLowerCase();
replaced = string.replace(/\s+/g, '+');
$http.jsonp('http://example.com/query='+replaced+'&callback=JSON_CALLBACK').success(function(data) {
console.dir(data.results);
$scope.movies = data.results;
});
imgSrc = document.getElementById('myImage').src;
ext = imgSrc.split('.').pop();
missing='http://example.com/missing.jpg';
if(ext !== 'jpg'){
imgSrc = missing;
}
});
}
</script>
.
Qualche idea con quello che sto sbagliando, o se quello che sto tentando può anche essere fatto affatto?
Soluzione
Il primo problema che posso vedere è che mentre si imposta il movies
in una callback Async, stai cercando la sorgente immagine in modo sincrono qui:
$http.jsonp('http://domain.com/query='+replaced+'&callback=JSON_CALLBACK').success(function(data) {
console.dir(data.results);
$scope.movies = data.results;
});
// This code will be executed before `movies` is populated
imgSrc = document.getElementById('myImage').src;
ext = img.split('.').pop();
.
Tuttavia, spostando il codice solo nel callback non risolverà il problema:
// THIS WILL NOT FIX THE PROBLEM
$http.jsonp('http://domain.com/query='+replaced+'&callback=JSON_CALLBACK').success(function(data) {
console.dir(data.results);
$scope.movies = data.results;
// This will not solve the issue
imgSrc = document.getElementById('myImage').src;
ext = img.split('.').pop();
// ...
});
.
Questo perché i campi src
saranno popolati solo nel successivo digest loop .
Nel tuo caso, dovresti potare i risultati non appena li ricevi dalla richiamata JSONP:
function movieSearch($scope, $http, $timeout){
var string,
replaced,
imgSrc,
ext,
missing;
$(document).on('keyup', function(){
string = document.getElementById('search').value.toLowerCase();
replaced = string.replace(/\s+/g, '+');
$http.jsonp('http://domain.com/query='+replaced+'&callback=JSON_CALLBACK').success(function(data) {
console.dir(data.results);
$scope.movies = data.results;
$scope.movies.forEach(function (movie) {
var ext = movie.poster_path && movie.poster_path.split('.').pop();
// Assuming that the extension cannot be
// anything other than a jpg
if (ext !== 'jpg') {
movie.poster_path = 'missing.jpg';
}
});
});
});
}
.
Qui, si modifica solo il model
dietro la visualizzazione e non eseguire alcuna analisi DOM post-hoc per capire i guasti.
.
Sidenote: È stato possibile utilizzare l'operatore ternario per risolvere il problema nella vista, ma questo non è consigliato:
<!-- NOT RECOMMENDED -->
{{movie.poster_path && ('http://domain.com/'+movie.poster_path) || 'http://domain.com/missing.jpg'}}
. Altri suggerimenti
In primo luogo, ho definito un filtro come questo:
in CoffeeScript:
app.filter 'cond', () ->
(default_value, condition, value) ->
if condition then value else default_value
.
o in JavaScript:
app.filter('cond', function() {
return function(default_value, condition, value) {
if (condition) {
return value;
} else {
return default_value;
}
};
});
.
Allora, puoi usarlo come questo:
{{'http://domain.com/missing.jpg' |cond:movie.poster_path:('http://domain.com/'+movie.poster_path)}}
.