[Alloy] 개별 Child View간의 아이템에 접근하기

안녕하세요, 더위 속에서 안녕히 잘 계신가요!
그래도 오늘은 비가 와서 선선하니 좋네요 :slight_smile:

질문 드릴 내용은, 예전에 질문드렸던 것과 조금 비슷한데요.
우선 index 뷰에 2개의 child 뷰를 불러왔습니다.

var navView = Alloy.createController('navView'}).getView();
var dashView = Alloy.createController('dashView'}).getView();

$.container.add(dashView);
$.navView.add(navView);
$.index.open();

navView는 네비게이션 역할을 하는 뷰로 따로 생성해서 관리하고 있고요, dashView는 그냥 child 뷰라고 보시면 될 것 같습니다.

여기서, dashView에서 발생하는 이벤트에 따라 navView라는 네비게이션 뷰에 속한 Label의 text 속성을 변경하고 싶습니다. 네비게이션 뷰는 요렇게 구성되어 있습니다.

<Alloy>
	<View id="navView">
		<Button id="leftBtn">
			<ImageView id="leftCover" class="profBtn"/>
		</Button>
		<Label id="navTitle" text='test111'/>
		<Button id="rightBtn">
			<ImageView id="rightCover"/>
		</Button>
	</View>
</Alloy>

이 경우에 navTitle의 text를 또 다른 child뷰인 dashView의 컨트롤러에서 변경해줄 수 있을까요?
단순히 parent 뷰에서 child 뷰는 @heedoo님께 배웠었는데, 이 경우는 조금 어렵네요…

부탁드립니다!

여러가지 방법으로 해결할 수 있겠죠.

어떤 방법이든 잊지말하야 할 사항은, 이벤트 기반으로 프로그래밍을 할때 중요한 각 컨트롤러가 의존성을 최대한 없애야 한다는 것입니다.
위의 예시로 풀어서 얘기해보면 원하는 사항이 navView의 변화에 따라 dashView의 내용을 변하게 하고 싶다고 dashView 코드 내에 navView를 다루는 부분이 들어가는 것은 바람직하지 않다는 것입니다.

이런경우에 상위(index)에서 이벤트를 엮어주거나, global한 event dispatcher를 두거나, 값이 수시로 변하는것이 아니라면 상위(index)에서 값을 전달해 주는 방식이 있을 수 있습니다.

개략적으로 코드를 작성해보자면 아래와 같습니다.

// index.js에서 엮어주는방법
var navViewC = Alloy.createController('navView'});
var dashViewC = Alloy.createController('dashView'});

navViewC.navTitle.addEventListner('change',function(){
    dashViewC.doSomething();
});

// 저는 navTitle과 같이 직접 view에 접근하기보다는 외부적으로 나가야하는 이벤트가 있다면 해당 컨트롤로의 on/tirgger를 통한 Alloy 커스텀 이벤트를 이용하는 것을 선호합니다.
// navViewC.on('navTitle:change',function() { ...});
// index.js 에서 공통 데이터를 내려주고 각 컨트롤러에서는 넘겨받은 값을 처리
var data = {
    title : 'whatever'
}

var navView = Alloy.createController('navView'}, data).getView();
var dashView = Alloy.createController('dashView'}, data).getView();
2개의 좋아요

코드까지… 흑 자세한 답변 감사합니다!
의존성에 대해 언급해주신 부분도 항상 조심해야겠습니다 :slight_smile:

좋은 주말 마무리 되세요.

컨트롤러를 만들때는 종은님 처럼 argument를 이용하구요.
또 다른 방법으로는 컨트롤러에 exports.functionname = function 으로 인터페이스를 만들어서 제공하는 것도 가능합니다.
하지만 이경우 역시 객체가 강하게 결합 되기 때문에, 컨트롤러를 만든 이후에는 event를 발생시켜서 처리하는 방법을 많이 사용합니다.
Trigger로 이벤트를 발생시키고, 다른 컨트롤러에서 이것을 on으로 listen하고 있다가 처리하지요.

마지막으로 뷰를 동적으로 더하시는 경우가 아니라면 alloy xml의 require를 추천드립니다.
뷰의 구성을 더 직관적으로 가져갈 수 있고, 스타일 처리도 쉬워서요.

이미 포스트하신 시간이 많이 지났지만 혹시 같은 것을 고민하시는 분들을 위해
@DongWoo_Gim 님이 언급하신 Require 방법에 관해 코드 남깁니다.

//navBar.xml
<Alloy>
    <View class="container">
        <Label id="title"/>
    </View>
</Alloy>

//dashView.xml
<Alloy>
    <View class="container">
        <Require src="navBar" id="navBar"/>
    </View>
</Alloy>
//dashView.js
//xml에 require 으로 정의 하시면 아래처럼 값을 변경하실 수 있답니다. 
$.navBar.title.text = "My Title is this"