Dodawanie dwóch takich samych obiektów do tablicy

0

Hej,

tworzę generowanie dokumenty zamówienia sprzedaży. Mam dropdowna z wyborem towaru, pole input z ilością i przycisk dodaj.
Dodaję coś takiego:

export interface ISku {
  id: number;
  code: string;
  name: string;
  codeName: string;
  uom: string;
  quantity: number;
}

do tablicy

const orderPositions = ref<Array<ISku>>([]);

dodaje towar do zamówienia w taki sposób

const sku = ref<ISku>({
  id: 0,
  code: "",
  name: "",
  codeName: "",
  uom: "",
  quantity: 0,
});

// ta metoda rusza gdy wybiorę towar z dropdowna
const pickSku = (value) => {
  let item = skus.value.filter((item) => {
    return item.id == value;
  });

  item[0].quantity = 1;

  sku.value = item[0];
};    

// tutaj gdy klik w button "dodaj pozycje"
const addOrderPosition = () => {
  if (sku.value?.quantity) sku.value.quantity = skuQuantity.value;

  orderPositions.value.push(sku.value);
};  

wyświetlam tak

<tbody>
  <tr v-for="(row, index) in orderPositions" :key="index">
    <td>{{ row.code }}</td>
    <td>{{ row.name }}</td>
    <td>
      <el-input-number
        v-model="row.quantity"
      />
    </td>
    <td>
      <a @click="deleteOrderPosition(row.id)" class="menu-link px-3">
        <i class="fa fa-trash text-danger"></i>
      </a>
    </td>
  </tr>
</tbody>

problem mam taki, że gdy dodam dwa razy ten sam towar i zmieniam jednemu z nich wartość quantity w inpucie w tabelce powyżej. Steruje obiema wartościami jednocześnie.

Próbowałem do ISku dodać property z jakimś generowanym GUIDEM ale nie dało rezultatów. Szybko robiłem i chyba zrobię to raz jeszcze dla testu.
GUID = jakiś id unikalny wiersza by się przydał również dla operacji usunięcia pozycji. Bo w tej chwili szukając po sku.id usuwam 1szy znaleziony co w przypadku 2 takich samych nie da rady działać poprawnie.

Zresztą użycie w pętli :key="index" - próbowałem użyć tego.

1

Możliwe, że problem jest z tym:

  let item = skus.value.filter((item) => {
    return item.id == value;
  });

Musisz robić kopię obiektu poczytaj choćby https://devszczepaniak.pl/kopiowanie-obiektow-w-javascript/

0
  let item = skus.value.filter((item) => {
    return item.id == value;
  });

  item[0].quantity = 1;

jeśli zależy ci na wyszukaniu obiektu, to masz do tego metodę find
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

wtedy powyższy kod można zapisać bez potrzeby tworzenia dodatkowej tablicy:

  let item = skus.value.find((item) => {
    return item.id == value;
  });

  item.quantity = 1;

(nie mówię, że kod powyżej będzie poprawny w kontekście całej aplikacji (w szczególności nic on nie zmieni w konktekście tego, o co pytasz), raczej chodzi mi tylko o ten konkretny pattern, że zamiast tworzyć nową tablicę przez filter i robić item[0], to można od razu użyć find i mieć od razu ten konkretny element)

nie kumam też, czemu robisz skus.value, czy nie powinieneś używać samego skus?

skus.find(......)

Ale to moje przypuszczenie tylko, bo nie widzę całego kodu.

Poza tym tak jak przedmówca wspomniał, potrzebna ci kopia obiektu.

0

@LukeJL: to fakt aby to uprościć
@kAzek: to dobry trop jednak nie wychodzi
przerobiłem jednak nadal dodanie tego samego obiektu powoduje mój problem. Dodawanie wszystkich innych towarów działa poprawnie.

    const pickSku = (value) => {
      let item = skus.value.find((item) => {
        return item.id == value;
      });

      // we are sure that item is always found so non-null assertion operator is used to avoid "Object is possibly 'undefined'."
      item!.quantity = 1;

      //Object.assign({}, item);
      //{ ...item[0] };
      sku.value = JSON.parse(JSON.stringify(item));
    };
1
john_doe napisał(a):
  // we are sure that item is always found so non-null assertion operator is used to avoid "Object is possibly 'undefined'."
  item!.quantity = 1;

Tylko, że działa jedynie na poziomie kompilacji TypeScripta. Jednak w dalszym ciągu item mógłby być undefined, jeśli nie zostałby znaleziony w tablicy:

     let item = skus.value.find((item) => {
        return item.id == value;
      });

a wtedy wyskoczy wyjątek w czasie odpalania programu.

Więc lepszą praktyką byłoby upewnienie się, czy faktycznie item został znaleziony:

  let item = skus.value.find((item) => {
    return item.id == value;
  });
  if (item) {
     item.quantity = 1;
  }
0

Może tak:

orderPositions.value.push(JSON.parse(JSON.stringify(sku.value)));

1 użytkowników online, w tym zalogowanych: 0, gości: 1