์š”๊ตฌ์‚ฌํ•ญ > ์„œ๋น„์Šค ๊ธฐํš > UI, UX ์ƒ์„ธ ์„ค๊ณ„ > GUI ๋””์ž์ธ > ํผ๋ธ”๋ฆฌ์‹ฑ > ๋ฐฑ์—”๋“œ API ๊ฐœ๋ฐœ > ํ”„๋ŸฐํŠธ์—”๋“œ ๊ฐœ๋ฐœ > QA

night owl material icon theme vetur vue vscode snippets

https://github.com/joshua1988/vue-til-server

  • ๋ฒ„์ „ Node.js ์ด์ „ ๋ฆด๋ฆฌ์ฆˆ ๋‹ค์šด๋กœ๋“œ ํŽ˜์ด์ง€ https://nodejs.org/ko/download/releases/ OS ๋ณ„๋กœ ์•„๋ž˜ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์œผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค ๐Ÿ˜ƒ ์œˆ๋„์šฐ 64๋น„ํŠธ : x64-msi ํŒŒ์ผ ์œˆ๋„์šฐ 32๋น„ํŠธ : x86-msi ํŒŒ์ผ ๋งฅ : pkg ํŒŒ์ผ ๋ฆฌ๋ˆ…์Šค : tar ํŒŒ์ผ NVM ์„ค์น˜ ์ง„ํ–‰ ๋ช…๋ น์–ด https://gist.github.com/falsy/8aa42ae311a9adb50e2ca7d8702c9af1

  • https://github.com/nvm-sh/nvm#installing-and-updating

    *vscode terminal.integrated.shell.window

bash๋กœ ๋ณ€๊ฒฝ ์‚ฌ์šฉ์ž์— ํด๋”์—์„œ .bash_profile ํŒŒ์ผ์ถ”๊ฐ€

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash

nvm -v nvm use system vi ~/.bash_profile

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

source ~/.bash_profile

nvm install 12.14.0 nvm install 10.16.3

# vue click async

https://stackoverflow.com/questions/64883186/basic-async-call-on-click-event-in-template-vuejs

# vue computed

https://velog.io/@jinsu6688/vuejs-computed

# vue dx-grid row

https://stackoverflow.com/questions/5497073/how-to-differentiate-single-click-event-and-double-click-event

# vue smart editor2 image upload

https://javafactory.tistory.com/1259 http://naver.github.io/smarteditor2/user_guide/2_install/download.html https://zero-gravity.tistory.com/171 https://github.com/naver/smarteditor2/releases/tag/v2.8.2.3 http://webprogramer.kr/blog/P000000364/post.do http://www.todayhumor.co.kr/board/view.php?table=programmer&no=11347 https://holybell87.tistory.com/12

* ์‚ฌ์šฉ๋ฒ„์ „ : 2.8.2.12056
1. /SE2.8.2.O12056/sample/js/plugin/hp_SE2M_AttachQuickPhoto.js
var sPopupUrl = "์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ํŒ์—…์ฐฝ ํ‘œ์‹œURL"; ๋กœ ์ˆ˜์ •

2. ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ํŒ์—…์ฐฝ์„ ํ†ตํ•ด, ์—…๋กœ๋“œ ํ•œ ํ›„
   Smart Editor์— ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  function์„ ํ˜ธ์ถœํ•˜๋Š” ๋ถ€๋ถ„์—์„œ
window.opener.parent.function์ด๋ฆ„(); ์š”๋ก ์‹์œผ๋กœ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
 

Smart Editor๊ฐ€ iFrame์œผ๋กœ ์ƒ์„ฑ๋˜๋‹ˆ...

์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด ๋†“์ง€ ์•Š์•˜๋‹ค๋ฉด
์š”๊ธฐ๋กœ ๊ฐ€๋ฉด, JSP๋กœ ๋งŒ๋“ค์–ด ๋†“์€ ๋ถ„์ด ๊ณ„์‹œ๋‹ค.

http://zero-gravity.tistory.com/171

https://lilymate.tistory.com/476

# vue grid edit

https://js.devexpress.com/Documentation/Guide/UI_Components/DataGrid/Editing/#User_Interaction/Row_Mode https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/Vue/Light/

# vue grid addrow

https://js.devexpress.com/Demos/WidgetsGallery/Demo/FloatingActionButton/Overview/Vue/Light/

<dx-button class="btn--input" width="68" height="34" text="์ถ”๊ฐ€" @click="addNewRow" />
<dx-button class="btn--input" width="68" height="34" text="์™„๋ฃŒ" @click="saveGridInstance" />

  saveGridInstance() {
    console.log('aaaa')
    // debugger
    // this.grid.instance.beginUpdate()
    // this.grid.instance.closeEditCell()
    this.grid.instance.saveEditData()
    // this.grid.instance.refresh()
    console.log('bbb')
  }

# devextreme customstore remove

https://js.devexpress.com/Documentation/ApiReference/Data_Layer/CustomStore/

# devextreme popup

    <h3 class="hy-h3 required">ํŒ์—…</h3>
    <div class="row-box mgt-20">
      <dx-button class="btn--input" height="34" text="ํŒ์—…์˜คํ”ˆ" @click="popupOpen()" />
    </div>
    <!-- ํŒ์—…์‹œ์ž‘ -->
    <dx-popup :visible.sync="show" width="600" title="ํŒ์—…๊ฐ€์ด๋“œ">
      <div class="sub-head">
        ์„œ๋ธŒ ํ—ค๋” ์˜์—ญ
      </div>
      <!-- ์Šคํฌ๋กค์ด ํ•„์š” ์—†์„ ๊ฒฝ์šฐ ์‚ญ์ œ -->
      <DxScrollView class="scrollview" ref="scrollViewWidget">
        <!-- popup -->
        <div class="hy-popup">
          ํŒ์—… ์ฝ˜ํ…์ธ  ์˜์—ญ...
    
          <div class="btn-wrap center">
            <!-- ์ขŒ์šฐ ์ •๋ ฌ span.left ์‚ฌ์šฉ -->
            <!-- <span class="left">
                              <dx-button class="btn--base" width="120" height="40" text="์ทจ์†Œ" />
                            </span> -->
            <dx-button class="btn--base" width="120" height="40" text="์ทจ์†Œ" @click="popupClose" />
            <dx-button class="btn--solid" width="120" height="40" text="์Šน์ธ์š”์ฒญ" />
          </div>
        </div>
      </DxScrollView>
    </dx-popup>
    <!-- ํŒ์—… ์ข…๋ฃŒ -->
  show: boolean = false

  popupOpen() {
    console.log('open')
    this.show = true
  }

  popupClose() {
    console.log('close')
    this.show = false
  }

# devextreme textbox showclearbutton

<dx-text-box v-model="searchCondition.id" :show-clear-button="true" />

https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxTextBox/Configuration/#showClearButton

# vue style ์ ์šฉ

<div v-show="!!text4" :style="{ display: !!text4? 'inline-block' :'none' }"> </div>

# devextreme excel upload

  <u-file-upload-box
    v-model="result2"
    file-grp-id="file4"
    select-button-text="์—‘์…€ํŒŒ์ผ ์—…๋กœ๋“œ"
    upload-type="convert"
    converted-file-type="excel"
    model-class-name="com.test.FileExcelSampleModel"
    :stop-on-error="true"
    :saveable="false"
    :editable="true"
  />

# devextreme image upload


https://codesandbox.io/s/jgpcd2?file=/App.vue
https://codesandbox.io/s/jgpcd2?file=/App.vue:334-345

# vue import alias

import { DxToolbar, DxItem, DxSelection, DxEditing, DxDataGrid } from 'devextreme-vue/data-grid'
import { DxToolbar as DxToolbar2, DxItem as DxItem2, DxSelection as DxSelection2, DxEditing as DxEditing2, DxDataGrid as DxDataGrid2 } from 'devextreme-vue/data-grid'

# vue error

https://nodejs.org/download/release/v16.17.1/


internal/modules/cjs/loader.js:818
  throw err;
  ^
Error: Cannot find module 'node:fs'


node_modules/rc9/dist/index.cjs
rc9/dist/index.cjs

https://cocoon1787.tistory.com/851
https://cocoon1787.tistory.com/851
https://medium.com/@su_bak/cannot-find-module-fs-promises-%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5-%E1%84%92%E1%85%A2%E1%84%80%E1%85%A7%E1%86%AF-%E1%84%87%E1%85%A1%E1%86%BC%E1%84%87%E1%85%A5%E1%86%B8-a344921bd430

# vue prop

prop์„ค์ •ํ›„์—๋Š” f5 ์ง„ํ–‰ํ›„ ํ•˜๊ธฐ

// @Prop({ default: '' }) fileId: string @Prop() fileId: string = '' (x) Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "fileId"

https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxDataGrid/Configuration/columns/#cellTemplate

# vue grid focused-row-changing

      <dx-data-grid ref="grid" :data-source="gridData" width="100%" height="100%" @focused-row-changing="onFocusedRowChanging" @focused-row-enabled="true" key-expr="regDttm">
        <dx-column alignment="center" width="100%" data-field="rownum" caption="๋ฒˆํ˜ธ" />
        <dx-column alignment="center" width="100%" data-field="regUsrId" caption="์ž‘์„ฑID" />
        <dx-column alignment="center" width="100%" data-field="regDttm" caption="์ž‘์„ฑ์ผ" :calculate-cell-value="data => formatters.datetime(data.regDttm)" />
        <dx-column alignment="center" width="100%" data-field="updUsrId" caption="์ˆ˜์ •ID" />
        <dx-column alignment="center" width="100%" data-field="updDttm" caption="์ˆ˜์ •์ผ" :calculate-cell-value="data => formatters.datetime(data.regDttm)" />
      </dx-data-grid>

// onSelectionChanged({ selectedRowsData }) {
  //   debugger
  //   const data = selectedRowsData[0]
  //   alert('ss')
  // }

  clickTimer: any
  lastRowCLickedId: any
  onFocusedRowChanging(e) {
    //OBTAIN YOUR GRID DATA HERE
    console.log('test')
    if (this.clickTimer && this.lastRowCLickedId === e.rowIndex) {
      console.log('aaaa')
      clearTimeout(this.clickTimer)
      this.clickTimer = null
      this.lastRowCLickedId = e.rowIndex

      const key = e.event && e.event.key
      if (e.event.detail === 2) {
        // alert('test')
      }
      //YOUR DOUBLE CLICK EVENT HERE
      // if (typeof dblClickFunc == 'function') {
      // }
    } else {
      this.clickTimer = setTimeout(function () {}, 250)
    }
    this.lastRowCLickedId = e.rowIndex
  }

  // const pageSize = e.component.pageSize()
  // const pageIndex = e.component.pageIndex()
  // const isLoading = e.component.getController('data').isLoading()
  // const key = e.event && e.event.key
  // if (!isLoading) {
  //   if (key && e.prevRowIndex === e.newRowIndex) {
  //     if (e.newRowIndex === pageSize - 1) {
  //       e.component.pageIndex(pageIndex + 1).done(() => {
  //         e.component.option('focusedRowIndex', 0)
  //       })
  //     } else if (e.newRowIndex === 0) {
  //       e.component.pageIndex(pageIndex - 1).done(() => {
  //         e.component.option('focusedRowIndex', pageSize - 1)
  //       })
  //     }
  //   }
  // }
  // }

#

# ๋ฐฉ๋ฒ•1 node ์žฌ์„ค์น˜

  1. node 12๋ฒ„์ „ ์‚ญ์ œ
  2. ์žฌ์„ค์น˜ https://nodejs.org/download/release/v16.17.1/

# ๋ฐฉ๋ฒ•2 nvm ์‚ฌ์šฉ์‹œ

  1. nvm install 16.17.1
  2. nvm use 16.17.1
  3. nvm alias default 16.17.1

# vue grid

    this.gridDataSource = new DataSource({
      store: new CustomStore({
        load: async loadOptions => {
          const paginationRequest = createPagingParameter(loadOptions)
          const result = await orderConsignmentListService.getOrderConsignmentList(paginationRequest.header, this.params)
          this.gridData = result.body
          this.totalCount = result.header.totalRecords
          return {
            data: this.gridData,
            totalCount: result.header.totalRecords,
          }
        },
      }),
    })


    this.gridDataSource = new DataSource({
      store: this.gridData
    });

# databindiing

https://js.devexpress.com/Documentation/Guide/UI_Components/PivotGrid/Data_Binding/

# CustomStore

https://supportcenter.devexpress.com/ticket/details/t428982/customstore-how-to-process-load-options-provided-by-dxdatagrid

# vue grid paging

https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RecordPaging/Vue/Light/

<dx-scrolling 
  mode="standard"
  column-rendering-mode="virtual"
  :use-native="false"
  />
<dx-paging
  :enabled="true"
  :page-size="10"
  :page-index="0" />
<dx-pager 
  :show-page-size-selector="true"
  :show-info="true"
  info-text="ํ˜„์žฌ ํŽ˜์ด์ง€ {0}. ์ „์ฒดํ•ญ๋ชฉ: {2}๊ฐœ" />
<DxScrolling row-rendering-mode="virtual"/>
<DxPaging :page-size="10"/>
<DxPager
  :visible="true"
  :allowed-page-sizes="pageSizes"
  :display-mode="displayMode"
  :show-page-size-selector="showPageSizeSelector"
  :show-info="showInfo"
  :show-navigation-buttons="showNavButtons"
/>
  displayMode:string =  'full'
  pageSizes: any[] = [5, 10, 'all']
  showPageSizeSelector: boolean =true
  showInfo: boolean=true
  showNavButtons: boolean=  true

# vue style

style="visibility: hidden" style="display: none"

# vue dx-list

<div class="col">
  <strong>๋Œ€๋ถ„๋ฅ˜</strong>
  <dx-list
    v-model="fstCtgValue"
    :data-source="fstCtgIds" 
    display-expr="codeNm"
    :height="175"
    selection-mode="single"
    page-load-mode="scrollBottom"
    :search-enabled="true"
    search-mode="contains"
    search-expr="codeNm"
    @selection-changed=selectionChangedFirst($event)
    />
</div>
<div class="col">
  <strong>์ค‘๋ถ„๋ฅ˜</strong>
  <dx-list 
    v-model="scdCtgValue"
    :data-source="scdCtgIds"
    :height="175"
    selection-mode="single"
    page-load-mode="scrollBottom"
    :search-enabled="true"
    search-mode="contains"
    search-expr="codeNm"
    @selection-changed=selectionChangedSecond($event)
    >
    <template #item="{ data: data, index: index }">
      {{ data.codeNm}}
    </template>  
  </dx-list>

</div>


<dx-list 
  v-model="scdCtgValue"
  :data-source="scdCtgIds"
  :height="175"
  selection-mode="single"
  @selection-changed=selectionChangedSecond($event)
>
  <template #item="{ data: row, index: index }">
    <!-- <ul class="temp" style='display: none'> -->
    <ul class="temp" v-if='index== 2'>
      <li>
          {{ index }}
          {{ row.code}}
      </li> 
    </ul>
  </template>  
</dx-list>

# vue dom ์‚ฌ์šฉ

https://bono915.tistory.com/entry/VueJS-refs%EC%9C%BC%EB%A1%9C-Dom%EC%97%90-%EC%A0%91%EA%B7%BC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

# vue for

    <template v-for="(item, index) in fileInfo" >
      <template>
        <dd class="hy-attch" v-bind:key="item.fileName" >
            <a href= "javascript:;" @click="()=>{download(item.fileGrpId, item.fileId, item.fileNo, '', 1)}">{{ item.orgName }}</a>
        </dd>
      </template>
    </template>

# File chooser dialog can only be shown with a user activation.


# vue emit and model

// parent -emit ๋ฐฉ์‹
<editor-product-regist @value="changeDatass"/>
  changeDatass(data: string) {
    console.log('my!!!', data)
  }

// parent - ๋ชจ๋ธ๋ฐฉ์‹
<editor-product-regist v-model="changeData"/>

  changeData: string = ''

  @Watch('changeData')
  changeData() {
    console.log(this.changeData)
  }

// child

  @Model('value', { default: null }) readonly value

  @Watch('content', { immediate: true })
  changeContent() {
    this.$emit('value', this.content)
  }

# vue paging

<dx-scrolling 
  mode="standard"
  column-rendering-mode="virtual"
  :use-native="false"
  />
<dx-paging
  :enabled="true"
  :page-size="10"
  :page-index="0" />
<dx-pager 
  :visible="true"
  :show-page-size-selector="true"
  :show-info="true"
  info-text="ํ˜„์žฌ ํŽ˜์ด์ง€ {0}. ์ „์ฒดํ•ญ๋ชฉ: {2}๊ฐœ" 
  />

  @Ref() readonly grid: DxDataGrid
  gridData: OrderConsignmentList[] = []
  loadParam: any

  async loadData() {
    this.loadParam = {
      "currentPage": 1,
      "pageSize": 10,
      "orders": []
    }
    const paginationRequest = createPagingParameter(this.loadParam)
    const result = await testService.getSelect(paginationRequest.header, this.params)
    this.gridData = result.body
    this.totalCount = result.header.totalRecords
  }

  async search(params) {
    this.params = params
    this.loadData()
  }

# vue promise

.catch(error => alert(error.message));

.then(response => response.json())

# vue devextreme grid insert

this.gridDataSource = this.grid.instance.getDataSource()
this.gridDataSource.store().push([{ type: 'insert', data: newDeliveryFee }])

# vue devextreme grid checkbox

:selection="{ mode: 'multiple', showCheckBoxesMode: 'onClick' }"
      @selection-changed="onListSelectionChanged"

onListSelectionChanged(e) {
    alert('temp')
    if (e.selectedRowsData && e.selectedRowsData.length > 0) {
      // this.disableRemoveButton = false
    } else {
      // this.disableRemoveButton = true
    }
  }

# vue devextreme theme

https://js.devexpress.com/Documentation/Guide/Themes_and_Styles/Icons/
https://js.devexpress.com/Demos/WidgetsGallery/Demo/Button/Icons/Vue/Light/

# vue se2

https://junesker.tistory.com/16
https://m.blog.naver.com/hiizero/221639344451
http://naver.github.io/smarteditor2/user_guide/4_photouploader/intro.html
http://naver.github.io/smarteditor2/user_guide/

# vue devextreme data-period-box

<dx-date-period-box v-model="dateInput5" :width="150" mode="datetime" />

# vue window postmessgae

http://guide.ustraframework.kro.kr/ref-doc/03/5wtYKOTfWycqrQuucpyn

# vue grid option

<dx-data-grid
  :data-source="gridDataSource"
  :show-borders="true"
  :allowColumnReordering="true"       // <===== ๊ทธ๋ฆฌ๋“œ ์ปฌ๋Ÿผ ์œ„์น˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์—ฌ๋ถ€
  :allowColumnResizing="true"
  :row-alternation-enabled="false"
  :show-row-lines="true"
  :column-min-width="80"
>
:allowColumnReordering="true"       // <===== ๊ทธ๋ฆฌ๋“œ ์ปฌ๋Ÿผ ์œ„์น˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์—ฌ๋ถ€
:allowColumnResizing="true"         // <===== ๊ทธ๋ฆฌ๊ทธ ์ปฌ๋Ÿผ ์‚ฌ์ด์ฆˆ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์—ฌ๋ถ€
<dx-selection mode="single" /> // <==== multiple ์ฒดํฌ๋ฐ•์Šค, single ์„ ํƒํ•œ ๋ผ์ธ ๋ณด์ด๊ธฐ, none ์•„๋ฌด๊ฒƒ๋„ ์—†์Œ
<pager.infoText>
{0} - ํ˜„์žฌ ์„ ํƒํ•œ ํŽ˜์ด์ง€ (shows the current page number.)
{1} - ์ „์ฒด ํŽ˜์ด์ง€ (shows the total page count.)
{2} - ์ „์ฒด ํ–‰ ๊ฐœ์ˆ˜ (shows the total row count.)

# vue devextreme grid template

<dx-data-grid ref="grid" :data-source="gridData" width="100%" height="100%">
   <dx-column alignment="center" width="100%" data-field="postId" caption="๋ฒˆํ˜ธ" />
   <dx-column :width="100" :allow-sorting="false" data-field="Picture" cell-template="cellTemplate"/>
   <template #cellTemplate>
      <img src="http://localhost/image.png">
   </template>
</dx-data-grid>
https://codesandbox.io/s/ixjl38?file=/App.vue
https://supportcenter.devexpress.com/ticket/details/t657515/how-to-show-an-image-in-datagrid-column
https://js.devexpress.com/Documentation/Guide/UI_Components/DataGrid/Columns/Customize_Cells/#Customize_the_Appearance
https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/ColumnTemplate/Knockout/Light/

# vue addEvent

https://stackoverflow.com/questions/55067565/vue-js-add-event-listener-inside-instance

# vue devextreme exprot xlsx, pdf

https://shiftkey.tistory.com/28
https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxDataGrid/Configuration/export/
https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/ExcelJSOverview/Vue/Light/

# vue devextreme grid cell change

  <dx-data-grid id="sampleGrid" ref="grid" :data-source="gridData" width="100%" height="600"
    :selected-row-keys="selectedItemKeys" :show-borders="true" @editorPreparing="onEditorPreparing"
    @editingStart="onEditingStart($event)">

  onEditingStart(e) {
    // e.column.allowEditing = true
    // console.dir(e.column.name)
    // // debugger
    // console.dir(e.key.postId == 43)
    // if (e.column.name == "isChecked") {
    //   if (e.key.isChecked == true) {
    //     e.cancel = true;

    //     console.log('testa')
    //   }
    // }

    // }
    // console.dir()
    // if (info.key == 2) {
    // info.cancel = true;
    // }
  }

  onEditorPreparing(e) {
    // console.dir(e.row.isSelected)
    // console.log('onEditorPreparing')
    if (e.parentType === 'dataRow' && e.dataField === 'isChecked' && e.row.isSelected == true) {
      console.log('test')

      e.row.isSelected = true
      // e.editorOptions.disabled = true
    }
  }    

# vue model add

import { ProofFile } from '@/models/data-model'

getUploadList() {
  var fileIdList = [{ etpsCd: 'a100', fileId: 'aaaaa', fileTpCd: 'F100' }, { etpsCd: 'b100', fileId: 'bbbbb', fileTpCd: 'F200' }]
  var updateList = []
  fileIdList.map(row => {
    let proofFile: ProofFile = {
      fileId: row.fileId,
      etpsCd: row.etpsCd,
      fileTpCd: row.fileTpCd,
      fileNo: 1,
    }
    updateList.push(proofFile)
  })
}

# vue refs ์‚ฌ์šฉ

<file-upload-product-regist fileGrpId="default-file-group" ref = "refFileUpload" />
  getFileList() {
    const val = (this.$refs['refFileUpload'] as FileUpload).getUploadList()
    val.map(test => { console.dir(test) })
  }

# vue typeof ์™€ instanceof์˜ ์ฐจ์ด, ํƒ€์ž… ๋˜๋Š” ํด๋ž˜์Šค ๊ตฌ๋ถ„ํ•˜๊ธฐ

https://unikys.tistory.com/260

# vue arr์ธ์ง€ ํ™•์ธ

Array.isArray()

https://hianna.tistory.com/402

# vue tap index

<dx-tab-panel :selected-index.sync="tabIndex2" :data-source="tab2" height="100%" :width:="500"
  @selection-changed="tab2IndexChanged">
  <template #title="{ data }">
    <span>{{ data.name }}</span>
  </template>
  <template #tab1>
    <!-- <sub-tab ref="grid1" /> -->
  </template>
  <template #tab2>
    <!-- <sub-tab ref="grid2" /> -->
  </template>
  <template #tab3>
    <!-- <sub-tab ref="grid3" /> -->
  </template>
</dx-tab-panel>

  tabIndex2 = 0

  tab2 = [
    { name: '๊ฒฐ์ œ๊ฑด์ˆ˜', template: 'tab1', disabled: false },
    { name: '๊ฒฐ์ œ์ž์ˆ˜', template: 'tab2', disabled: false },
    { name: '๊ฒฐ์ œ๊ธˆ์•ก', template: 'tab3', disabled: false },
  ]

  tab2IndexChanged() {
    if (this.tabIndex2 === 0) {
      // @ts-ignore
      // this.$refs.grid1.loadData()
    } else if (this.tabIndex2 === 1) {
      // @ts-ignore
      // this.$refs.grid2.loadData()
    } else if (this.tabIndex2 === 2) {
      // @ts-ignore
      // this.$refs.grid3.loadData()
    }
  }

# vue config, querystring

@Component({
  config: {
    auth: {
      required: false
    }
  },
})

  created() {
    console.log('created')
    console.dir(this.$route.query)
  }

# vue notion

https://www.npmjs.com/package/vue-notion?activeTab=readme

# vue querystring

  funcQueryString(data: any) {
    var keys = []
    for (var number in data) {
      if (data.hasOwnProperty(number)) keys.push(number)
    }
    var querysting = ''
    keys.map((row, index) => {
      if (index == 0) querysting += `?${row}=${data[row]}`
      else querysting += `&${row}=${data[row]}`
    })
    return querysting
  }

# vue devextreme floating action button


    <DxSpeedDialAction :index="1" icon="" label="์ „์ฒด ํƒญ ๋‹ซ๊ธฐ" :on-click="() => success= true" />


import config from 'devextreme/core/config';
import FloatingActionButtonDirection from 'devextreme/core/config';
import repaintFloatingActionButton from 'devextreme/ui/speed_dial_action/repaint_floating_action_button';~~~~
import DxSpeedDialAction from 'devextreme-vue/speed-dial-action';

    config({
      floatingActionButtonConfig: {
        icon: 'rowfield',
        shading: true,
        direction: 'down',
        position: {
          of: '.dx-datagrid-rowsview',
          my: 'right top',
          at: 'right top',
          offset: '-20 90',
        },
      },
    });

    repaintFloatingActionButton();

https://js.devexpress.com/Demos/WidgetsGallery/Demo/FloatingActionButton/Overview/Vue/Light/

# vue devextreme icon

<dx-button icon="deletetable" v-if="menu.text == 'Home'" @click="clickCloseAllTab()" />

https://js.devexpress.com/Documentation/Guide/Themes_and_Styles/Icons/

# vue devextreme validator

https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxValidator/Validation_Rules/PatternRule/
https://js.devexpress.com/Demos/WidgetsGallery/Demo/Validation/Overview/Vue/Light/

# vue devextreme textbox mode ์˜ค๋ฅ˜

// dx-text-box๊ฐ€ password๋ฅผ ๋ˆ„๋ฅธ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ํ…์ŠคํŠธ ๋ฐ•์Šค๋ฅผ ๋ˆ„๋ฅผ๊ฒฝ์šฐ ๋ชจ๋“œ๊ฐ€ ๊ธฐ์กด์— ํด๋ฆญํ•œ mode๋กœ ๋˜๋Š” ํ˜„์ƒ
<dx-text-box ref="refTextBox" class="side-search-input" v-model="searchText" mode="search"
        placeholder="์ž…๋ ฅ" value-change-event="input" :readOnly="!isFocused" @focusIn="focusIn()"
        @focusOut="focusOut()" />

@Ref() refTextBox: DxTextBox
  focusIn() {
    this.isFocused = true
    this.refTextBox.mode = "text"
  }
  focusOut() {
    this.isFocused = false
    this.refTextBox.mode = "text"
  }


# vue file upload download

https://stackoverflow.com/questions/41803925/download-octet-stream-via-jquery
https://kyounghwan01.github.io/blog/JS/JSbasic/Blob-url/
https://stackoverflow.com/questions/37510801/convert-octet-stream-to-image


# nuxt gitlab [error] Couldn't find any versions for

์›์ธ: gitlab์—์„œ nexus์— ํŒจํ‚ค์ง€์˜ ํŠน์ • ๋ฒ„์ „์ด ์‚ญ์ œ๋˜๋ฉด์„œ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜

์ ๊ฒ€1: gitlab์—์„œ ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” cd /app/gitlab-runner/builds/aaa/0/aaa
=> .npmrc ํ™•์ธ, yarn install ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ, yarn๊ด€๋ จ ํŒŒ์ผ ์‚ญ์ œํ›„ ์ง„ํ–‰ ๋“ฑ

์ ๊ฒ€2: gitlab-ci.yml
=> ์Šคํฌ๋ฆฝํŠธ ํ™•์ธ

์ ๊ฒ€3: nexus ์ด๋™ํ›„ ์ ๊ฒ€ Browser
=> ํ•ด๋‹น ํŒจํ‚ค์ง€๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™•์ธ

git-runner 
.npmrc


Run yarn again.
Run yarn --force.
If it still does not help, you can wipe yarn.lock and run yarn again.

# vue security

import VueSanitize from "vue-sanitize";
Vue.use(VueSanitize);

https://dev.grapecity.co.kr/bbs/board.php?bo_table=Insight&wr_id=118

# vue cell color change


vm.statusData = [];
vm.statusData = [
    {
        "iStatus": 1,
        "sName": "No Work",
        "sDesc": "No Work Done",
        "dPercentComplete": 0,
        "sColor": "Red"
    },
    {
        "iStatus": 2,
        "sName": "WIP",
        "sDesc": "Work In Progress",
        "dPercentComplete": 50,
        "sColor": "Yellow"
    },
    {
        "iStatus": 3,
        "sName": "Complete",
        "sDesc": "Work Complete",
        "dPercentComplete": 100,
        "sColor": "Green"
    }
];

onCellPrepared: function(e) {
  if (e.rowType != "data" || e.columnIndex != 1)
    return;
  
  // debugger;  
  var color = e.column.lookup.items[e.value - 1].sColor  
  e.cellElement.css('backgroundColor', color);

},

https://supportcenter.devexpress.com/ticket/details/t571121/dxdatagrid-how-to-set-a-custom-cell-color-based-on-a-lookup-value
https://plnkr.co/edit/Cr8UZvI1hxRY60CBDxX3?p=preview&preview

# volar

"volar.inlayHints.eventArgumentInInlineHandlers": true

# security

"><script>alert("XSS")</script>
"><script>alert("XSS")</script>

" onclick=alert(1)//<button ' onclick=alert(1)//> 
" onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)//


"><marquee/onstart=confirm(String.fromCharCode(88,
"><marquee/onstart=confirm(String.fromCharCode(88,83,83))>//


<html>
  <body onload="document.forms[0].submit()">
    <form action="https://testsite.com/logout">
    </form>
  </body>
</html>

# ์ค‘๋ณต์ฒดํฌ

// ํ™•์ธํ•  ๊ฐ’
const checkedList = this.refProductDxDataGrid.instance.getSelectedRowsData()

this.gridData.map(row => { if (row.testId.lastIndexOf(checkedList[0].testId) > -1) flag = true })

this.gridData.some(row => row.testId === checkedList[0].testId)

# isEmpty

isEmpty(val) {
  var result = false
  if (val != null && val != 'undefined' && val != '') {
    result = true
  }
  return result
}

# references

https://junior-datalist.tistory.com/236

Last Updated: 4/13/2025, 11:14:44 PM