При загрузке страницы (Vue cli), не отображаются дефолтные значения v-model (полученые асинхронно)
Пытаюсь сделать price-range, при отображении стр. получаю данные минимальной и максимальной цены, присваиваю эти значения ref и использую для связывания v-model. Когда стр загрузилась, все значения = 0, как только в скрипте делаю какие нить изменения, все работает как нужно. Подскажите пожалуйста что не так делаю
template:
<template>
<div class="nav-item-price">
<div class="nav-item-price__header">
<p class="nav-item-price__title">Price</p>
</div>
<div ref="filterBody" class="nav-item-price__body">
<div class="price-control">
<div class="price-control__counters">
<div class="price-control__inputs">
<label class="price-control__min-price">
<input
type="text"
maxlength="6"
name="min-price"
v-model="minPrice"
class="price-control__number"
/>
</label>
<span class="price-control__line"></span>
<label class="price-control__max-price">
<input
type="text"
maxlength="6"
name="max-price"
v-model="maxPrice"
class="price-control__number"
/>
</label>
</div>
<ButtonRegular class="price-control__button" @click="setPriceRange">
OK
</ButtonRegular>
</div>
<div class="price-control__range-slider">
<div class="price-control__progress">
<span class="price-control__bg-line"></span>
</div>
<input
type="range"
:min="priceRange.min"
:max="priceRange.max"
step="1"
v-model.number="minPrice"
@change="setRangeSlider"
/>
<input
type="range"
:min="priceRange.min"
:max="priceRange.max"
step="1"
v-model.number="maxPrice"
@change="setRangeSlider"
/>
</div>
</div>
</div>
</div>
</template>
script:
<script setup>
import ButtonRegular from "~~/modules/shared/components/buttons/ButtonRegular.vue";
import { useCriteriaStore } from "~~/store/criteriaStore";
import { useAllQueryParamsStore } from "~~/store/allQueryParamsStore";
const criteriaStore = useCriteriaStore();
const { getPriceRange: priceRange } = storeToRefs(criteriaStore);
const { minPrice: defaultMinPrice, maxPrice: defaultMaxPrice } =
useRoute().query;
const minPrice = ref(defaultMinPrice || priceRange.value.min);
const maxPrice = ref(defaultMaxPrice || priceRange.value.max);
//const temp = ref(0);
const calculate = (minMax) => {
if (minMax === "min") {
return Math.ceil(
((minPrice.value - priceRange.value.min) /
(priceRange.value.max - priceRange.value.min)) *
100,
);
} else {
return Math.ceil(
((priceRange.value.max - maxPrice.value) /
(priceRange.value.max - priceRange.value.min)) *
100,
);
}
};
const positionLeft = ref(`${calculate("min")}%`);
const positionRight = ref(`${calculate("max")}%`);
const filterBody = ref(null);
const initialHeight = ref(0);
const heightContent = ref("0");
const showFilters = ref(false);
const showFilter = ref(false);
const isOpenFilter = ref(true);
function setRangeSlider() {
if (minPrice.value > maxPrice.value) {
[maxPrice.value, minPrice.value] = [minPrice.value, maxPrice.value];
}
}
function setPriceRange() {
const router = useRouter();
const route = useRoute();
const queryParamsStore = useAllQueryParamsStore();
queryParamsStore.setMinPrice(minPrice.value);
queryParamsStore.setMaxPrice(maxPrice.value);
router.push({
path: route.path,
query: { ...queryParamsStore.getQueryParamsForURL },
});
}
watch(minPrice, (val) => {
positionLeft.value = `${calculate("min")}%`;
});
watch(maxPrice, (val) => {
positionRight.value = `${calculate("max")}%`;
});
</script>
style:
<style lang="scss" scoped>
.price-control {
@include flex-container(column, flex-start);
gap: 26px;
padding: 0 8px;
&__counters {
@include flex-container(row, space-between);
gap: 8px;
}
&__inputs {
@include flex-container(row, flex-start, center);
gap: 8px;
}
&__min-price,
&__max-price {
width: max-content;
border: 1px solid #8a8a8a;
border-radius: 4px;
padding: 6px 8px;
}
&__number {
width: 46px;
@include font(12, 18, 400);
letter-spacing: 0.02em;
color: #2b2b2b;
}
&__line {
width: 12px;
height: 1px;
background-color: #2b2b2b;
}
&__button {
@include font(12, 15, 400);
letter-spacing: 0.02em;
@include bigMobile {
width: 50%;
}
@include mobile {
width: 100%;
}
}
&__range-slider {
width: 100%;
position: relative;
}
&__range-slider svg,
&__range-slider input[type="range"] {
position: absolute;
left: -2px;
bottom: 0;
}
&__progress {
width: 100%;
height: 3px;
position: absolute;
top: -5px;
z-index: 1;
border-radius: 5px;
background-color: #d1d1d1;
}
&__bg-line {
height: 100%;
position: absolute;
top: 0;
left: v-bind(positionLeft);
right: v-bind(positionRight);
z-index: 2;
background-color: #f36c21;
}
input[type="range"]::-webkit-slider-thumb {
position: relative;
top: 2px;
z-index: 2;
margin-top: -7px;
}
input[type="range"]::-moz-range-thumb {
position: relative;
top: 2px;
z-index: 2;
margin-top: -7px;
}
input[type="range"] {
width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
@-moz-document url-prefix() {
input[type="range"] {
pointer-events: none;
z-index: 20;
bottom: -7px;
}
input[type="range"]::-moz-range-thumb {
z-index: 10;
pointer-events: all;
}
}
input[type="range"]::-webkit-slider-runnable-track {
height: 3px;
border-radius: 5px;
background-color: #d1d1d1;
}
input[type="range"]::-webkit-slider-thumb {
position: relative;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: #f36c21;
margin-top: -8px;
cursor: pointer;
-webkit-appearance: none;
}
input[type="range"]::-moz-range-thumb {
width: 16px;
height: 16px;
border-radius: 50%;
border: none;
background-color: #f36c21;
margin-top: -8px;
}
}
.nav-item-price {
@include flex-container(column, space-between,);
border-bottom: 1px solid #d1d1d1;
padding: 0 0 16px 0;
gap: 16px;
&__header {
@include flex-container(row, space-between, center);
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
padding: 0 8px;
/* cursor: pointer; */
/* transition: margin-bottom 0.2s ease-in-out; */
/* &.active {
margin-bottom: 16px;
.nav-item-price__arrow {
transform: rotateZ(180deg);
}
} */
}
&__title {
@include font(16, 22, 400);
color: #2b2b2b;
letter-spacing: 0.02em;
}
/* &__arrow {
font-size: 0;
flex: 0 0 auto;
transition: transform 0.2s ease-in-out;
} */
&__body {
/* height: v-bind(heightContent); */
/* transition: height 0.2s ease-in-out; */
/* overflow: hidden; */
}
}
/*
.test-price {
padding: 40px 5px 20px 5px;
&__wrp {
width: 100%;
position: relative;
padding: 0 30px;
}
&__line-bg {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 24px;
margin-top: 16px;
}
&__result {
position: relative;
width: 100%;
height: 2px;
background: #999;
cursor: pointer;
}
&__result-bg {
height: 2px;
background: #00a046;
&::before {
display: block;
position: absolute;
width: 28px;
height: 2px;
top: 0;
background: #999;
content: "";
left: -24px;
}
&:after {
display: block;
position: absolute;
width: 28px;
height: 2px;
top: 0;
background: #999;
content: "";
right: -24px;
}
}
&__min {
position: absolute;
top: 0;
display: block;
// transform: translateX(v-bind(sliderDiff)) ;
width: 24px;
height: 24px;
border: none;
border-radius: 50%;
background-color: #f5f5f5;
box-shadow: inset 0 0 0 1px #ebebeb;
cursor: pointer;
margin-left: -24px;
}
&__max {
position: absolute;
top: 0;
left: 100%;
display: block;
width: 24px;
height: 24px;
border: none;
border-radius: 50%;
background-color: #f5f5f5;
box-shadow: inset 0 0 0 1px #ebebeb;
cursor: pointer;
margin-right: -24px;
}
} */
</style>