이 위젯 템플릿을 오버라이드하려고 합니다:
api.reopenWidget("header-contents", {
template: hbs`
{{#if this.site.desktopView}}
{{#if attrs.sidebarEnabled}}
{{sidebar-toggle attrs=attrs}}
{{/if}}
{{/if}}
{{home-logo attrs=attrs}}
{{#if attrs.topic}}
{{header-topic-info attrs=attrs}}
{{else if this.siteSettings.bootstrap_mode_enabled}}
{{#if transformed.showBootstrapMode}}
{{header-bootstrap-mode attrs=attrs}}
{{/if}}
{{/if}}
<div class="panel clearfix" role="navigation">{{yield}}</div>
`,
});
현재 템플릿이 discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub 의 원본과 정확히 동일함에도 불구하고
다음과 같은 오류가 발생합니다:
아직 실제로 아무것도 “변경하지” 않았는데도 이런 일이 일어나는 것은 예상치 못한 것입니다.
이것이 유일한 수정 사항인 경우에도 이 문제를 재현할 수 있습니다.
결국 이 템플릿을 변경하려는 이유는, 토픽 라우트에서 들어갔다 나갔다 하지 않더라도 이 템플릿의 재평가를 강제할 수 있도록 하기 위해서입니다.
결국 카테고리 라우트에서 들어갔다 나올 때 위젯이 새로 고침되도록 강제하는 로직을 추가하고 싶습니다. 제 카테고리 라우트 표현 방식이 달라야 하기 때문입니다.
따라서 이 문제의 해결책 중 하나는 헤더 콘텐츠를 새로 고침하도록 강제하는 다른 방법을 찾는 것일 수 있습니다.
어쨌든, 이는 제가 기대하는 동작 방식처럼 보이지 않습니다?
david
(David Taylor)
4월 24, 2023, 12:22오후
2
이 부분에 시간을 많이 투자하고 싶지는 않습니다. 위젯은 머지않아 사라질 것이기 때문입니다. 어떤 커스터마이징을 시도하고 계신가요? 위젯 코드 안에 일반 플러그인 아웃렛을 추가할 수 있는 기능이 있으므로, 어딘가에 플러그인 아웃렛을 추가해 드릴 수 있을까요?
파일의 더 많은 부분을 공유해 주시겠어요? (예: hbs는 어디서 가져오고 있나요?)
david
(David Taylor)
4월 24, 2023, 12:26오후
3
그럼 이 Discourse의 버전은 무엇인가요? site-header.js:337에는 현재 ‘header’ 변수에 대한 참조가 없습니다.
알겠습니다.
import { hbs } from "ember-cli-htmlbars";
기능적으로 저는 라우트에 따라 로고를 전환하려고 합니다. 실제로는 일부 라우트에서 홈 로고에 이미지를 붙여넣고, 주요 로고 위에 오버레이를 겹쳐서 이를 수행하고 있습니다. 라우트 간 이동 시 해당 로직이 다시 평가되기를 원하는데, 현재는 header-contents 위젯에 모든 것이 첨부되어 있고, 이 위젯에는 attrs.topic을 평가하는 로직이 포함되어 있어 라우트 이동 시 당연히 변경되므로, Topic 라우트에서 들어오고 나갈 때는 작동하는 것으로 보입니다.
제 category-logo-widget은 다음과 같이 첨부됩니다:
api.decorateWidget("home-logo:after", (helper) => {
const currentPath = helper.register
.lookup("service:router")
.get("_router.currentPath");
if (
helper.widget.currentUser &&
!helper.widget.site.mobileView &&
currentPath.indexOf("discovery") === -1
) {
return helper.attach("category-logo-widget");
}
});
이것은 잘 작동하지만, 특정 라우트 전환 사이에 다시 평가되지 않아 페이지 리로드 없이 완전히 동적으로 요구 사항을 충족하지 못하고 있습니다.
아, 실수했습니다. 이것이 문제일 수도 있다는 느낌이 들었지만, 제 테스트는 너무 표면적이어서 이를 배제할 수 없었습니다.
이 커밋을 확인했습니다. 제 개발 인스턴스를 업데이트해야 할 것 같습니다 … PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub
어쨌든 되돌릴 것입니다. 시간 내주셔서 감사합니다!
david
(David Taylor)
4월 24, 2023, 12:50오후
5
이것이 문제일 가능성이 높습니다. 위젯 'templates’는 Discourse 고유의 기능이며, Ember 템플릿과는 완전히 다른 방식으로 컴파일됩니다. hbs는 다음과 같이 가져와야 합니다:
특정 라우트 전환 사이에 재평가(re-evaluated)되도록 하는 site-header:force-refresh 앱 이벤트가 있는 것 같습니다. 다른 앱 이벤트나 Ember 라우터 이벤트에 반응하여 이 이벤트를 트리거할 수 있습니다:
(트리거 예시: 여기 )
최고네요, 데이비드 감사합니다. 오래된 설치 문제를 수정하고, 여기서도 당신의 추천 사항을 시도해 보겠습니다. 여러 가지가 쌓여 있었는데, 정리해 주셔서 감사합니다!
아마도 좀 과한 것일 수 있지만, 결국 제안을 다음과 같이 활용했습니다:
api.onPageChange(url => {
const applicationController = container.lookup(
"controller:application"
);
applicationController.appEvents.trigger(
"site-header:force-refresh"
);
});
이것이 아주 잘 작동했습니다. 다만 라우트 전환과 완벽하게 동기화되지는 않지만, 괜찮습니다.
다시 한번 감사합니다!
참고로, 위젯 API는 전부 맞춤형으로 되어 있고 다소 까다롭습니다(특히 하이퍼스크립트 부분은 더욱 그렇습니다). 하지만 기존 위젯에 코드를 많이 오버라이드하지 않고도 새로운 동작을 붙이는 것이 매우 강력하다는 점은 인정해야 합니다.
예를 들어, 저는 이 패턴을 많이 사용했습니다:
api.reopenWidget('discourse-awesome-widget', {
html(attrs, state) {
let contents = this._super(...arguments);
contents.unshift(h("div.my-cool-new-thing", "cool new thing"))
return contents;
}
});
this._super에는 아주 많은 코드가 들어 있을 수 있습니다!!!
그리고 이보다 훨씬 더 정교한 방식으로 사용할 수 있어서, 이제는 이 기능을 정말로 높이 평가하게 되었습니다.
이것을 대체할 것이 어떤 것이든, 그 "오버라이드 가능성"이 이만큼이나 유연하고 강력하길 바랍니다.
david
(David Taylor)
5월 10, 2023, 8:03오전
9
여기서 주요 해결책은 플러그인 아웃렛(plugin outlets)이 될 것입니다. 항상 그랬듯, 존재하지 않는 아웃렛이 필요하다고 느끼시면 코어에 PR을 자유롭게 보내 주세요