콘텐츠로 이동

Markdown/HTML Card

Markdown/HTML Card 위젯은 대시보드에 Markdown이나 HTML 내용을 렌더링합니다. 정적 정보 표시, 템플릿 기반 데이터 카드, CSS로 꾸민 완전한 사용자 지정 HTML 레이아웃에 씁니다.

  • 실시간 엔티티 데이터로 바뀌는 ${key} 자리표시자를 넣어 정적 Markdown이나 HTML을 표시합니다.
  • JavaScript 값 함수로 내용을 코드로 만듭니다. 조건부 서식을 적용하거나, 여러 키를 합치거나, 복잡한 HTML을 구성할 수 있습니다.
  • 위젯 범위로 한정된 사용자 지정 CSS로 카드를 꾸밉니다.
  • <tb-dashboard-state>로 다른 대시보드 상태를 카드 안에 넣습니다. 공통 위젯을 복제하지 않고 탭 레이아웃을 만들 때 씁니다.
  1. 대시보드를 수정 모드로 엽니다. 위쪽 툴바의 위젯 추가를 클릭하거나, 빈 대시보드 가운데의 위젯 추가 아이콘을 클릭합니다.
  2. 위젯 번들 선택 대화상자에서 HTML widgets를 찾아 클릭합니다.
  3. Markdown/HTML Card 위젯을 선택합니다.
  4. 데이터 소스와 모양을 설정한 다음 추가를 클릭합니다.

위젯은 세 탭에서 설정합니다: 데이터(데이터 소스), 모양(HTML 내용과 스타일), 위젯 카드(위젯 카드 설정).

${key} 자리표시자를 채우거나 값 함수에 넘길 데이터의 소스를 선택합니다:

  • 장치 — 특정 HMI 장치. 위젯이 이 HMI 장치의 최신 속성과 텔레메트리 데이터로 자리표시자를 채웁니다.
  • 개체 별명 — 엔티티 별칭에 맞는 엔티티 집합. 대상 엔티티를 실행 중에 동적으로 고를 때 씁니다.
  • 기능 — JavaScript 함수로 데이터를 만듭니다. 시험할 때나 실제 HMI 장치가 필요 없을 때 씁니다.

데이터 소스를 설정하지 않으면 위젯은 실시간 데이터를 넣지 않은 정적 템플릿을 렌더링합니다.

마크다운/HTML 패턴 필드에 Markdown이나 HTML을 직접 입력합니다. ${key}로 실시간 값을 넣고, ${key:N}으로 소수 자릿수를 정합니다.

마크다운/HTML 패턴 필드
### Temperature value card
- **Current entity**: ${entityName}
- **Current temperature**: ${temperature:1} °C

내용을 코드로 만들려면 마크다운/HTML 값 함수 사용 스위치를 켭니다. 함수는 엔티티별 최신 값이 담긴 data 배열을 받아 HTML 문자열을 돌려줘야 합니다.

값 함수 편집기
const entity = data[0];
const color = entity.temperature > 25 ? "red"
: entity.temperature > 20 ? "green"
: "blue";
return `### Temperature value card
- Current entity: <span>${entity.entityName}</span>
- Current temperature: <span style="color:${color};">${entity.temperature.toFixed(1)} °C</span>`;

위젯의 CSS 탭에 사용자 지정 CSS를 추가합니다. Markdown/HTML 템플릿에서 쓴 클래스 이름으로 스타일을 지정할 수 있습니다.

CSS 스타일 탭

마크다운/HTML 패턴:

<div class="office-card">
<h3>${entityName}</h3>
<p class="blue-box">
<strong>Current temperature:</strong>
<span class="temp-value">${temperature:1}</span> °C
</p>
<p class="green-box">
<strong>Current humidity:</strong>
<span class="hum-value">${humidity:0}</span> %
</p>
</div>

마크다운/HTML CSS:

.office-card {
box-sizing: border-box;
padding: 15px;
margin: 6px 0;
text-align: center;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, "Noto Sans";
}
.office-card h3 {
margin: 0 0 12px;
font-size: 24px;
}
.blue-box {
background: #2196F31A;
border: 2px solid #2196F3;
border-radius: 10px;
padding: 10px;
margin: 8px 0;
font-weight: 700;
}
.green-box {
background: #4CAF501A;
border: 2px solid #4CAF50;
border-radius: 10px;
padding: 10px;
margin: 6px 0;
font-weight: 700;
}

카드 수준 설정은 위젯 카드 탭에서 합니다.

설정설명
제목위젯 헤더에 표시되는 글자.
카드 아이콘제목 옆에 표시하는 아이콘.
배경 색카드 배경. CSS로 배경을 정할 때는 #FFFFFF00(투명)으로 정합니다.
카드 모서리 반경카드 모서리의 둥근 정도.
카드 패딩카드 내용과 테두리 사이 간격. HTML 템플릿이 자체 패딩을 관리하면 0으로 정합니다.
카드 버튼 표시전체화면을 켜고 끕니다. Data export는 PE, PaaS, PaaS/EU에서만 쓸 수 있습니다.

Markdown/HTML Card는 다음 소스에서 위젯 동작을 지원합니다:

  • 카드 클릭 시 — 사용자가 카드의 아무 곳이나 클릭하면 실행됩니다.
  • 위젯 헤더 버튼 — 위젯 헤더 표시줄에 사용자 지정 버튼을 추가합니다.

목표: 사무실 자산의 주소, 관리자, 전화, 이메일 속성을 아이콘이 있는 정보 카드에 꾸며서 표시합니다.

1단계. 엔티티 준비. 이 CSV로 사무실 자산을 가져옵니다: office_a_asset.csv. 자산에는 서버 속성 address, officeManager, phone, email이 있어야 합니다.

2단계. 위젯 추가. 대시보드를 수정 모드로 열고 위젯 추가를 클릭하고 HTML widgets를 선택한 다음 Markdown/HTML Card를 고릅니다.

3단계. 데이터 소스 설정. 데이터 탭에서 데이터 소스를 사무실 자산 엔티티로 정합니다. 데이터 키로 address, officeManager, phone, email을 추가합니다.

4단계. 값 함수 설정. 모양 탭에서 마크다운/HTML 값 함수 사용을 켜고 JavaScript 함수를 붙여 넣습니다:

if (data.length) {
const buildingAttributes = ['address', 'officeManager', 'phone', 'email'];
let information = {
entityName: data[0].entityName ? data[0].entityName : 'Not found',
buildingAttributesField: {}
};
for (let key of buildingAttributes) {
information.buildingAttributesField[key] = data[0][key] ? data[0][key] : 'Not found';
}
const attributesNotFound = Object.values(information.buildingAttributesField)
.every(value => value === 'Not found');
if (attributesNotFound) {
return '<div class="no-data-card">' +
'<h1 class="card-title">Information on ' + information.entityName + '</h1>' +
'<div class="no-data-block"><div class="no-data-content">' +
'<p class="no-data-title">There is no information about the building</p>' +
'</div></div></div>';
} else {
return '<div class="card">' +
'<h1 class="card-title">Information on ' + information.entityName + '</h1>' +
'<div class="attributes">' +
'<div class="attribute_container"><div class="icon_wrapper"><tb-icon class="icon">place</tb-icon></div>' +
'<div><div class="attribute_label">Address</div><div class="attribute">' + information.buildingAttributesField.address + '</div></div></div>' +
'<div class="attribute_container"><div class="icon_wrapper"><tb-icon class="icon">person</tb-icon></div>' +
'<div><div class="attribute_label">Manager</div><div class="attribute">' + information.buildingAttributesField.officeManager + '</div></div></div>' +
'<div class="attribute_container"><div class="icon_wrapper"><tb-icon class="icon">call</tb-icon></div>' +
'<div><div class="attribute_label">Phone</div><div class="attribute">' + information.buildingAttributesField.phone + '</div></div></div>' +
'<div class="attribute_container"><div class="icon_wrapper"><tb-icon class="icon">mail_outline</tb-icon></div>' +
'<div><div class="attribute_label">Email</div><div class="attribute">' + information.buildingAttributesField.email + '</div></div></div>' +
'</div></div>';
}
}

5단계. CSS 추가. 마크다운/HTML CSS 필드에 CSS 스타일을 붙여 넣습니다:

.card, .no-data-card { padding: 0px; height: 100%; }
.card-title { position: sticky; top: 0; z-index: 2; font-size: 16px; letter-spacing: 0.25px; padding: 16px; }
.attribute_container { display: flex; align-items: center; gap: 20px; padding: 16px; border-bottom: 1px solid #0000000d; }
.icon { z-index: 1; }
.icon_wrapper { display: flex; position: relative; align-items: center; padding: 8px; border: 1px solid var(--tb-primary-100, #305680); border-radius: 4px; }
.icon_wrapper:before { content: ''; z-index: 0; position: absolute; opacity: 0.1; background-color: var(--tb-primary-200, #305680); width: 100%; height: 100%; left: 0; top: 0; }
.attribute, .attribute_label { font-size: 14px; line-height: 20px; }
.attribute_label { color: #00000061; }
.no-data-card { display: flex; flex-direction: column; }
.no-data-block { display: flex; flex-direction: column; justify-content: center; height: 100%; max-width: 345px; padding: 0 15px; margin: 0 auto; text-align: center; }
.no-data-content { transform: translateY(-30%); }
.no-data-block p { font-weight: 500; }
.no-data-title { color: rgba(0, 0, 0, 0.54); }

6단계. 저장. 추가를 클릭하고 필요하면 크기와 위치를 조정한 다음 대시보드 툴바의 저장을 클릭합니다.

결과: 카드에 사무실 이름, 주소, 관리자, 전화, 이메일이 아이콘과 함께 표시됩니다. 속성이 없으면 그 필드에 “Not found”가 표시됩니다.


위젯 내용이 비어 있음

원인해결 방법
자리표시자 키를 찾을 수 없음${key} 이름이 데이터 소스의 데이터 키 라벨과 정확히 같은지 확인합니다. 키 이름은 대소문자를 구분합니다.
데이터 소스가 설정되지 않음${key} 자리표시자를 쓰면 맞는 데이터 키가 있는 데이터 소스를 설정해야 합니다.
HMI 장치가 데이터를 보내지 않음장치 → 최근 데이터를 열고 키에 최근 값이 있는지 확인합니다.

값 함수가 아무것도 출력하지 않거나 오류를 냄

원인해결 방법
return 문이 빠짐함수는 HTML 문자열을 명시적으로 돌려줘야 합니다. 모든 코드 경로가 값을 돌려주는지 확인합니다.
data[0]이 undefined임데이터 소스에 결과가 없으면 함수가 빈 data 배열을 받습니다. 보호 코드를 추가합니다: if (!data.length) return '';
JavaScript 문법 오류브라우저 콘솔을 열어 정확한 오류와 줄 번호를 확인합니다.

CSS 스타일이 적용되지 않음

원인해결 방법
클래스 이름이 맞지 않음CSS의 클래스 이름이 HTML 템플릿의 클래스 이름과 정확히 같은지 확인합니다.
위젯 기본 스타일이 스타일을 덮어씀더 구체적인 CSS 선택자를 쓰거나, 최후의 수단으로 !important를 추가합니다.