Обновление массива с различными вариантами шаблонов

Рассмотрим ситуацию, когда необходимо отобразить сложный список, в каждом пункте которого, есть дополнительный вариант шаблона, например в некоторых пунктах есть параграф с дополнительным текстом, а в некоторых нет.

Давайте создадим разметку для данного списка:

<div class="container-fluid">
    <div class="row">
        <div class="col-12">

<!--------------------------------->  

        <div data-test_array="array" class="row">
         <!-- массив test_array с контейнерами списка test_container -->

            <div data-test_container="container" class="card col-3">
                <p data-test_container-main_text="text">контейнер 1</p>
                <div data-test_container-variant="render-variant">  <!-- свойство с типом render-variant - для отображения дополнительного шаблона -->

                     <div data-variant_cont_1="container">  <!-- первый вариант шаблона -->
                        <p data-variant_cont_1-text="text" data-variant_cont_1-style="style" > текст варианта 1 </p>
                     </div>

                </div>
            </div>
            <div data-test_container="container" class="card col-3">
                <p data-test_container-main_text="text">контейнер 2</p>
                <div data-test_container-variant="render-variant">

                     <div data-variant_cont_2="container">  <!-- второй вариант шаблона -->
                        <p data-variant_cont_2-text="text" data-variant_cont_2-style="style" > текст варианта 2 </p>
                        <p data-variant_cont_2-text2="text">дополнительный текст</p>
                     </div>

                </div>
            </div>
            <div data-test_container="container" class="card col-3">
                <p data-test_container-main_text="text">контейнер 3</p>
                <div data-test_container-variant="render-variant">

                     <div data-variant_cont_1="container">  <!-- первый вариант шаблона -->
                        <p data-variant_cont_1-text="text" data-variant_cont_1-style="style" > текст варианта 3 </p>
                     </div>

                </div>
            </div>


        </div>


  <!--------------------------------->  
        </div>  
    </div>
</div>

Итак выше мы создали разметку которую выдает сервер при первом запросе

Далее создадим описание приложения:

var StateMap = {

    test_array: { //основной шаблон

        container: "test_container",
        props: ["variant", "main_text"],
        methods: {


        },      
    },
    virtualArrayComponents: {

        var_array_1:{
            container: "variant_cont_1", //первый вариант дополнительного шаблона
            props: ["text", "style"],
            methods: {


            }           
        },
        var_array_2:{
            container: "variant_cont_2", //второй вариант дополнительного шаблона
            props: ["text", "style", "text2"],
            methods: {


            }           
        },          
    }   
}

window.onload = function(){

    var HM = new HtmlixState(StateMap);

    console.log(HM);

    console.log(HM.state["test_array"].getAll());


}

Итак мы создали приложение со всеми компонентами, которые затем вывели в консоль.

Тепреь к примеру мы нажали на кнопку пагинации и перешли на другую страницу, и сервер нам прислал в fetch запроссе json объект с данными для новой страници:

    var resp = [

    {main_text: "Название 1", variant: {componentName: "var_array_2", text: "оновной текст 1", style: "color: red;", text2: "дополнительный текст1"} },
    {main_text: "название 2", variant: {componentName: "var_array_1", text: "оновной текст 2", style: "color: yellow;"} },
    {main_text: "название 3", variant: {componentName: "var_array_2", text: "оновной текст 3", style: "color: red;", text2: "дополнительный текст2"} },
    {main_text: "название 2", variant: {componentName: "var_array_1", text: "оновной текст 2", style: "color: yellow;"} },

    ];

Итак мы получили новые данные с сервера, ключами которых являются названия свойств, первое свойство основного шаблона у нас main_text с типом "text", а второе свойство это variant с типом "render-variant" в него сервер вложил объект с данными для дополнительного шаблона, а также имя дополнительного шаблона componentName,

Теперь нам необходимо обновить интерфейс на основании полученных данных, первый способ это удалить все из массива вызвав метод .removeAll() в массиве, затем в цикле добавлять новые контейнеры conainer = test_array.add(newProps), потом в каждом контейнере удалить старый вариант шаблона conainer.variant.renderChild.remove(true); затем создать новый вариант шаблона templ = rootLink.state[componentName].add(newProps); Затем добавить в контейнер новый вариант conainer.variant.renderByContainer(templ);

И второй более легкий способ это вызвать: HM.state["test_array"].reuseAll(resp); с новыми данными сервера. Как он работает? во первых в ответе с сервера ключи объектов, должны совпадать с названиями свойств, во вторых, должно присутствовать имя отображаемого компонента componentName для свойств с типом "render-variant", таким образом мы просто вызываем метод setProp() на каждом свойстве и передаем в него данные с ключа объекта, в ключе variant мы передаем обязательное поле componentName с именем виртуального массива, остальные поля являются необязательными и если их не указать он возьмет их из шаблона.

Итак изменим код описания приложения:

 window.onload = function(){

    var HM = new HtmlixState(StateMap);


    var resp = [

    {main_text: "Название 1", variant: {componentName: "var_array_2", text: "оновной текст 1", style: "color: red;", text2: "дополнительный текст1"} },
    {main_text: "название 2", variant: {componentName: "var_array_1", text: "оновной текст 2", style: "color: yellow;"} },
    {main_text: "название 3", variant: {componentName: "var_array_2", text: "оновной текст 3", style: "color: red;", text2: "дополнительный текст2"} },
    {main_text: "название 2", variant: {componentName: "var_array_1", text: "оновной текст 2", style: "color: yellow;"} },

    ];

    window.setTimeout( function(){ 

    HM.state["test_array"].reuseAll(resp);

    console.log(HM.state["test_array"].getAll());

    }, 2000);



    console.log(HM);

    console.log(HM.state["test_array"].getAll());


}

Таким простым способом можно создавать различные ветвления, например если у каждого дополнительного варианта, будет еще какойто вариант или список с типом 'group' и т.д. приложение определит тип свойства которое мы хотим обновить и если ето "render-variant" оно сменит вариант шаблона на тот который мы указали в 'componentName' и установит ему свойства которые мы передали, а если это группа "group" то удалит все из группы и создаст новую из массива с объектами, который нужно будет разместить в значении ключа.

Так работает не только метод .reuseAll(resp), для массива, но и метод setAllProps(obgWidthProps) для контейнера и setProp(newProp) для любого свойства.