I have this small project I'm working at, and it's my first time ever using KnockoutJS (and a long while since I used javascript).
Any javascript carousel works with foreach
, until the array is updated. I have already tried using Glider, Slick and Owl plugins and they all end up doing the same thing:
- Document starts, foreach initiates, populates the carousel with cards fetched from URL. OK
- Using the
<select>
, I change the option which will return a different API URL based on it. OK - The foreach is restarted, the new content is thrown in the data-bind, but the last carousel remains in HTML, working (?)
- The new content doesn't work well with the carousel, as the items show stacked on top of each other.
The fourth step actually happened long before I understood what happened with carousels and lifecycle from KO; I had to use a handleBinding
to start the plugin function after the foreach was made. Problem is, when the foreach is updated, KO won't restart the whole view, just what's inside of it, so the handleBinding is ignored.
Also, I can't explain why, in the 3rd step, the last carousel keeps there.
Code:
Select
<div id="select-regiao" data-bind="with: localizacoes" class="form-group mb-0">
<select id="selected-option" data-bind="options: planosPorLocalizacao, value: planosSelecionados" class="custom-select select-oi mr-2">
</select>
</div>
Carousel, foreach, card...
<div class="owl-carousel owl-theme" data-bind="foreach: planos, carousel">
<!-- #region card do plano -->
<div class="mt-4 m-2">
<div class="card card-plano">
[... card content... ]
</div>
</div>
<!-- #endregion -->
</div>
Before </body>
<script src="assets/js/jquery-3.3.1.slim.min.js" type="text/javascript"></script>
<script src="assets/js/popper.min.js" type="text/javascript"></script>
<script src="assets/js/bootstrap.min.js" type="text/javascript"></script>
<script src='assets/bower_components/knockout/dist/knockout.js' type='text/javascript'></script>
<script src="assets/js/ko-models.js" type="text/javascript"></script>
<script src="assets/js/owl-2-2.3.4/dist/owl.carousel.min.js"></script>
My ko-models.js
:
$(document).ready(function() {
apiUrl = "link";
localizacoes = {
planosPorLocalizacao: ["Todos", "Rio de Janeiro, RJ", "São Paulo, SP"],
planosSelecionados: ["Todos"]
};
planos = [];
var vm = null;
var select = document.getElementById("selected-option");
select.addEventListener("change", function() {
if (select.value == "Rio de Janeiro, RJ") {
apiUrl = "other link";
} else if (select.value == "São Paulo, SP") {
apiUrl = "other link";
} else if (select.value == "Todos") {
apiUrl = "link";
}
console.log(select.value);
MostraPlanos();
});
function MostraPlanos() {
fetch(apiUrl).then(function(next) {
next.json().then(function(res) {
// ko.cleanNode({planos: res});
res.forEach(el => {
el.dependentePreco = el["dependente-preco"];
el.precoReal = el["preco"].split(",")[0];
el.precoCentavo = el["preco"].split(",")[1];
});
planos = res;
if(vm == null) {
vm = {
planos: ko.observable(planos),
localizacoes
};
ko.applyBindings(vm);
}
else{
vm.planos(planos);
vm.gliderCarousel();
}
});
});
}
MostraPlanos();
ko.bindingHandlers.carousel = {
update: function() {
$(".owl-carousel").owlCarousel({
loop:true,
margin:10,
nav:true,
responsive:{
0:{
items:1
},
600:{
items:3
},
1000:{
items:5
}
}
});
}
}
});