DEV Community

Lin
Lin

Posted on

Imitation Hema - Product Search Page (37)

Technology Stack
Appgallery Connect

Development Preparation
As development progresses, our application is gradually approaching completion. We now need to continue adding corresponding functions to unused buttons and components on the home page. In this section, we will implement a product search page, starting from the top down: first, a search bar, followed by a system-recommended list of popular searches.

Functional Analysis
Implementing the top search bar is relatively simple—we only need to use the corresponding Row layout to populate the components and show/hide them based on the input status. For the popular search list, we need to create a corresponding table in the cloud, populate the data, and then request data from the cloud database.

Code Implementation
Create the Corresponding Table
{
"objectTypeName": "search_hot_txt",
"fields": [
{"fieldName": "id", "fieldType": "Integer", "notNull": true, "belongPrimaryKey": true},
{"fieldName": "txt", "fieldType": "String" }
],
"indexes": [
{"indexName": "field1Index", "indexList": [{"fieldName":"id","sortType":"ASC"}]}
],
"permissions": [
{"role": "World", "rights": ["Read"]},
{"role": "Authenticated", "rights": ["Read", "Upsert"]},
{"role": "Creator", "rights": ["Read", "Upsert", "Delete"]},
{"role": "Administrator", "rights": ["Read", "Upsert", "Delete"]}
]
}
Corresponding Entity Class

class SearchHotTxt {
id: number;
txt: string;

constructor() {
}

getFieldTypeMap():  Map<string, string> {
    let fieldTypeMap = new Map<string, string>();
    fieldTypeMap.set('id', 'Integer');
    fieldTypeMap.set('txt', 'String');
    return fieldTypeMap;
}

getClassName(): string {
    return 'search_hot_txt';
}

getPrimaryKeyList(): string[] {
    let primaryKeyList: string[] = [];
    primaryKeyList.push('id');
    return primaryKeyList;
}

getIndexList(): string[] {
    let indexList: string[] = [];
    indexList.push('id');
    return indexList;
}

getEncryptedFieldList(): string[] {
    let encryptedFieldList: string[] = [];
    return encryptedFieldList;
}

setId(id: number): void {
    this.id = id;
}

getId(): number  {
    return this.id;
}

setTxt(txt: string): void {
    this.txt = txt;
}

getTxt(): string  {
    return this.txt;
}

static parseFrom(inputObject: any): SearchHotTxt {
    let result = new SearchHotTxt();
    if (!inputObject) {
        return result;
    }
    if (inputObject.id) {
        result.id = inputObject.id;
    }
    if (inputObject.txt) {
        result.txt = inputObject.txt;
    }
    return result;
}
Enter fullscreen mode Exit fullscreen mode

}

export { SearchHotTxt };
Corresponding DB Class

import { cloudDatabase } from '@kit.CloudFoundationKit';

class search_hot_txt extends cloudDatabase.DatabaseObject {
public id: number;
public txt: string;

public naturalbase_ClassName(): string {
return 'search_hot_txt';
}
}

export { search_hot_txt };
Create the Product Search Page and Implement the Bar

// Create corresponding variables first
@State text: string = ''
controller: TextInputController = new TextInputController()
@State searchTxt: SearchHotTxt[] = []
@State flag: boolean = false
@State isSearch: boolean = false
@State columns: number = 2
Implement the Layout

Row() {
Image($r('app.media.left_back'))
.height(20)
.width(20)
.onClick(() => {
router.back()
})

TextInput({ text: this.text, placeholder: 'Input product name to search', controller: this.controller })
  .placeholderColor(Color.White)
  .placeholderFont({ size: 16, weight: 400 })
  .caretColor(Color.White)
  .width(200)
  .fontSize(16)
  .fontColor(Color.White)
  .onChange((value: string) => {
      this.text = value
    if (value.length === 0) {
      this.isSearch = false
    }
  })
Text("Search")
  .border({width: 1, radius: 10, color: Color.White})
  .fontSize(14)
  .fontColor("#ffffff")
  .padding({left: 13, right: 13, top: 5, bottom: 5})
  .borderRadius(10)
  .onClick(async () => {
    if (this.text.trim() === '' && this.text.length === 0) {
      this.isSearch = false
      showToast("Search content cannot be empty")
    } else {
        this.isSearch = true
    }
  })
Enter fullscreen mode Exit fullscreen mode

}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.padding({top: 10, bottom: 10, left: 15, right: 15})
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
.backgroundColor("#ff0000")
Query Corresponding Data from the Cloud Database

async aboutToAppear(): Promise {
const history = await StorageUtils.getAll("history_list")
if (history !== '' && history !== undefined) {
this.searchHistoryList = JSON.parse(history)
}
let condition = new cloudDatabase.DatabaseQuery(search_hot_txt);
let listData = await databaseZone.query(condition);
let json = JSON.stringify(listData)
let data1: SearchHotTxt[] = JSON.parse(json)
this.searchTxt = data1
this.flag = true
}
Display the Search List

Text("Popular Searches")
.width('100%')
.fontSize(16)
.fontColor("#000000")
.fontWeight(FontWeight.Bold)
.padding({left: 15, top: 15})

Flex({wrap: FlexWrap.Wrap}) {
ForEach(this.searchTxt, (item: SearchHotTxt, index: number) => {
Text(item.txt)
.backgroundColor("#ffe7e5e5")
.fontColor("#000000")
.fontWeight(FontWeight.Bold)
.fontSize(16)
.padding(10)
.margin({top: 10, left: 10})
.borderRadius(5)
.onClick(() => {
this.text = item.txt
})
})
}

Top comments (0)