Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 13.12.2019, 17:33
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Не обновляется ссылочный объект
Здравствуйте, уважаемые. Вопрос из базовых, но у меня вызвал затруднения. Есть древовидная структура. Я в компоненте либо добавляю, либо редактирую узлы. После обновления/создания элемента во внешнем компоненте, он приходит у родителю и там пытается обновить переменную класса componentData. После этого, по идее, обновления должны прорисоваться в родителе. Но этого не происходит.

Обновление входящими данными:
getChangedItemToList(incomeItem ){
	if (incomeItem) {
		let oldItem = Util.getTreeItemById(incomeItem.id, this.componentData);
		if (oldItem) {	// Апдейт
			console.log("before", oldItem, this.componentData);
			oldItem = incomeItem;
			console.log("after", oldItem, this.componentData);
		} else {	// Вставка нового узла
			if(!incomeItem.parent_id) { // Рубрика
				this.componentData = [incomeItem, ...this.componentData];
			} else { // Обычный элемент
				const itemParent = Util.getTreeItemById(incomeItem.parent_id, this.componentData);
				if(!itemParent.children) itemParent.children = [];
				itemParent.children.unshift(incomeItem);
			}
		}
	}
}


А вот функция поиска узла дерева:
export class Util {
	static getTreeItemById(id: string, tree: IUniversalTreeNode[]): IUniversalTreeNode{
		for (let count = 0; count < tree.length; count++) {
			if(tree[count].id == id){
				return tree[count];
			} else if(tree[count].children && tree[count].children.length > 0){
				const res =  this.getTreeItemById(id, tree[count].children);
				if(res !== null) return res;
			}
		}
		return null;
	}
}


По идее getTreeItemById возвращает ссылку на элемент дерева. И если я этот элемент обновлю, то, в моем понимании, поскольку это ссылка, должен обновиться и объект, который содержит узел дерева, который я нашел (oldItem = incomeItem; ). Но если oldItem обновился, то this.componentData не изменился. Подскажите пожалуйста в чем ошибка.
Ответить с цитированием
  #2 (permalink)  
Старый 13.12.2019, 18:56
Аватар для destus
Профессор
Отправить личное сообщение для destus Посмотреть профиль Найти все сообщения от destus
 
Регистрация: 18.05.2011
Сообщений: 1,204

sniffysko,
Попробуй в конструкторе заинжектить ChangeDetectorRef сервис и вызвать cd.markForCheck() или cd.detectChanges() между 16 и 17 строчкой.
Код вообще рабочий?
Ответить с цитированием
  #3 (permalink)  
Старый 15.12.2019, 20:30
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Сообщение от destus Посмотреть сообщение
sniffysko,
Попробуй в конструкторе заинжектить ChangeDetectorRef сервис и вызвать cd.markForCheck() или cd.detectChanges() между 16 и 17 строчкой.
Код вообще рабочий?
Ваш совет, как я понимаю, предназначен принудительно активировать проверку изменения состояния данных. Я делал так: this.componentData = [...this.componentData].
Моя проблема заключается в том, что this.componentData НЕ обновляется после 6 строки первого блока кода. Т.е. код не работает. Не работает в том плане, что не происходит обновления this.componentData через ссылку на один из узлов в виде переменной oldItem. Т.е. по сути вопрос не имеет отношения к Angular, а больше к базовому JS.
В моем понимании должно было работать так:
1. Строка 3 -- находим ссылку на узел в дереве (oldItem). Работает.
2. Присваиваем новое значение переменной oldItem, и, поскольку она есть ссылка, одновременно обновляется значение уза в дереве componentData. Работает не так как надо: oldItem переприсваивается и получает новое значение, а componentData не обновляется.
Ответить с цитированием
  #4 (permalink)  
Старый 15.12.2019, 22:20
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 30,451

Сообщение от sniffysko
this.componentData = [incomeItem, ...this.componentData];
может
this.componentData.unshift(incomeItem)
Ответить с цитированием
  #5 (permalink)  
Старый 15.12.2019, 22:55
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Немножко не то. Нужно обновить/добавить элемент дерева:
interface IUniversalTreeNode {
    id: number;
    name: string;
    children?: IUniversalTreeNode[];
}

Что сути проблемы не меняет. :о(
А строка this.componentData = [...this.componentData] просто перегенерит объект.

Перепишу пример по другому:
function RandomFillItemsList() {
    let res = [];
    for(count = 0; count < 10; count++){
        res.push({
            num: count * 100,
            id: count * 10
        });
    }
    return res;
}

let itemList = [];
itemList = RandomFillItemsList();
let selectedItem = itemList[0];
console.log(itemList, selectedItem);
selectedItem = {num: 0, id: 0};
console.log(itemList, selectedItem);


Хочу, чтобы itemList[0] стал равным {num: 0, id: 0}.
Понимаю, что вопрос базовый, и мне жутко стыдно, но как переприсвоить элемент по ссылке?

Последний раз редактировалось sniffysko, 15.12.2019 в 23:20.
Ответить с цитированием
  #6 (permalink)  
Старый 15.12.2019, 22:58
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 30,451

Сообщение от sniffysko
просто перегенерит объект.
так зачем вы создаёте новый обьект, а не изменяите старый?
Ответить с цитированием
  #7 (permalink)  
Старый 15.12.2019, 23:34
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Сообщение от рони Посмотреть сообщение
так зачем вы создаёте новый обьект, а не изменяите старый?
Вероятно потому, что балбес. :о)
Но возвращаясь к сути своего вопроса, порывшись в интернетах нашел, что так как я хочу сделсть нельзя.
Весь алгоритм сводится к томы, что необходимо найти нужный объект, и найдя его в структуре, тут же обновить.
Ответить с цитированием
  #8 (permalink)  
Старый 16.12.2019, 05:22
Аватар для destus
Профессор
Отправить личное сообщение для destus Посмотреть профиль Найти все сообщения от destus
 
Регистрация: 18.05.2011
Сообщений: 1,204

sniffysko,
вообще если долго не думать, 6 строку так перепишите
Object.keys(incomeItem).forEach(key => oldItem[key] = incomeItem[key]);
Ответить с цитированием
  #9 (permalink)  
Старый 16.12.2019, 09:36
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Ключевой момент заключается в том, что это не массив, а дерево.
Решение для этого случая уже придумал, но главным разочарованием стало то, что oldItem = incomeItem не сработало.
Спасибо за участие и советы. Пошел писать кот.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Полностью удалить объект 1lider Events/DOM/Window 8 07.06.2018 18:20
Добавить объект в другой объект фонарик Общие вопросы Javascript 5 11.10.2015 01:57
Создать объект в объекте Bryant-24 Общие вопросы Javascript 3 10.07.2013 15:06
jQuery (Как открыть объект в этом же окне, щёлкнув по нему мышкой) Объект кусок карты hadzhimuratov (X)HTML/CSS 32 18.06.2012 16:54
Передать ссылку на объект а не объект возникновения события Blazze Events/DOM/Window 0 10.10.2011 23:45