วันอังคารที่ 14 เมษายน พ.ศ. 2563

[Review] การต่อ Notebook ออก Port VGA 2 จอ และมีจอ Notebook อีกรวมเป็น 3 จอ

มันเป็นปัญหาสำหรับผมมานานในการใช้งาน Notebook แล้วพยายามต่อออกจอมากกว่า 1 จอเนื่องจาก Port ที่มีมามีแค่ HDMI 1 Port ไม่สามารถต่อมากกว่านั้นได้ก็เลยจะต่อเพิ่มได้แค่ 1 จอ ผมเลยทำการซื้อ USB 3.0 แปลงเป็น VGA เพื่อต่อได้อีก 1 จอ กลายเป็นสอง ปัญหาคือ อะไร ละงั้น ?

ปัญหาคือ
1. ผมต้องเสียบ HDMI กับ USB 3.0 ซึ่งส่วนตัวไม่อยากทำแบบนั้น อยากลดลงเหลือแค่ HDMI หรือ USB อย่างไดอย่างหนึ่ง
2. ช่องต่อที่เป็น USB 3.0 มีแค่ 1 ช่องเท่านั้น และ USB 3.0 แปลงเป็น VGA มีความเพี้ยนของภาพทำให้รู้สึกไม่ดีเวลาใช้งาน

ผมจึงเริ่มตามหา USB 3.0 แปลงเป็น VGA แบบชัดขึ้น และก็เลยได้เจอกับตัว G-Link ครับลองสั่งมาเลย 2 ตัว เพื่อจะเปลี่ยนแทนตัว HDMI (เดิม HDMI ของผมเป็น HDMI แปลงเป็น VGA เหมือนกัน) และเจอว่ามี USB 3.0 Hub เลยสั่งมาด้วย เพราะจะต่อพวงกันไปเลย และผลที่ได้ก็น่าพอใจมากครับ คิดว่าถ้าจะเพิ่มอีกจอน่าจะไม่มีปัญหา แต่ตอนนี้ยังไม่มีจอ ก็พักก่อนหาเรื่องเสียเงินไปเรื่อย ๆ จริง ๆ

วันอาทิตย์ที่ 2 กุมภาพันธ์ พ.ศ. 2563

[Linux Container] - สร้าง Network และ Storage ไว้ก่อนแล้วค่อยมา Init

การใช้งาน Linux Container สักพักหนึ่งก็พบความไม่สะดวกในการใช้งาน Network กับ Storage ตอนที่ทำการ Init
Network ปกติจะ Init เป็น 10.x.x.x ทำให้ชนกับ Network ภายใน และ Storage ก็เพิ่มได้ยากเพราะหาไม่เจอ เลยทำการสร้างไว้ก่อน

สร้าง Network -> https://im-jumbo.blogspot.com/2019/04/how-to-use-lxc-network.html
สร้าง Storage -> https://im-jumbo.blogspot.com/2019/08/linux-container-storage-pool-lxc-storage.html

เมื่อทำการสร้าง Network กับ Storage เสร็จแล้วก็ทำการ Init ตามปกติ
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-76-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon Feb  3 14:55:06 +07 2020

  System load:  0.0               Users logged in:       0
  Usage of /:   7.8% of 77.26GB   IP address for ens192: 10.1.4.50
  Memory usage: 3%                IP address for ens224: 192.168.0.115
  Swap usage:   0%                IP address for lxdbr1: 172.168.0.1
  Processes:    202

 * Overheard at KubeCon: "microk8s.status just blew my mind".

     https://microk8s.io/docs/commands#microk8s.status

 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

0 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. 
Check your Internet connection or proxy settings


Last login: Mon Feb  3 14:44:48 2020 from 192.168.0.251
sarankon@conf:~$ lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]: no
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]: no
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
Name of the existing bridge or host interface: lxdbr1
Would you like LXD to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
sarankon@conf:~$

วันพฤหัสบดีที่ 30 มกราคม พ.ศ. 2563

Convert PFX File To PEM File By OpenSSL

การใช้ Cert กับ Apache2 ผมยังใช้งานกับไฟล์ PEM อยู่ซึกปกติแล้ว Cert ที่ได้มาจะเป็นไฟล์ PFX ผมเลยต้องทำการ Convert อีกครั้งก่อนใช้งานจริง
ขอบคุณข้อมูลจากเว็บ: https://www.xolphin.com/

# สร้างไฟล์ PEM ที่รวมทั้ง Private Key และ Certificate จากไฟล์ PFX
openssl pkcs12 -in filename.pfx -out cert.pem -nodes

# สร้างไฟล์ Private Key จากไฟล์ PFX
openssl pkcs12 -in filename.pfx -nocerts -out key.pem

# สร้างไฟล์ Certificate จากไฟล์ PFX
openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem

# ลบรหัสผ่านออกจาก Private Key
openssl rsa -in key.pem -out server.key

วันอังคารที่ 14 มกราคม พ.ศ. 2563

Angular 8 - การ Build เพื่อนำไปใช้งาน

ข้อมูลเพิ่มเติมอ่านได้จาก https://angular.io/start/deployment

การใช้งาน Angular เราต้องทำการ Build Project ของเราก่อนด้วยคำสั่ง ng build เสร็จแล้วจะได้ไฟล์พร้อมใช้งานอยู่ที่ Folder dist
ให้เราทำการ Copy ไฟล์ข้างในที่อยู่ในระดับเดียวกัน index.html ลงไป ไปว่างไว้ที่ Root Web ก็สามารถใช้งานได้
 
ng build --prod
ng build --prod --base-href=/project-name/

วันอาทิตย์ที่ 12 มกราคม พ.ศ. 2563

Angular 8 - การสร้าง Form สำหรับรับข้อมูล

การสร้าง Form เราจะต้องทำการ Import Module ชื่อ ReactiveFormsModule ในไฟล์ app.module.ts ก่อนถึงจะเรียกใช้งานใน Component อื่นๆ ได้
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { RouterModule } from '@angular/router';

import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
import { CartComponent } from './cart/cart.component';

@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailComponent,
    CartComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    ReactiveFormsModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'product/:productId', component: ProductDetailComponent },
      { path: 'cart', component: CartComponent}
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }

วันศุกร์ที่ 10 มกราคม พ.ศ. 2563

Angular 8 - เรียกข้อมูลแบบ JSON ผ่าน HTTPClient

เตรียมข้อมูล JSON ชื่อ shipping.json ใน Folder assets แล้วทดสอบเรียกผ่าน URL : "http://localhost:4200/assets/shipping.json"
[
    {
        "type": "Overnight",
        "price": "25.99"
    },{
        "type": "2-Day",
        "price": "9.99"
    },{
        "type": "Postal",
        "price": "2.99"
    }
]

วันพุธที่ 8 มกราคม พ.ศ. 2563

Angular 8 - บริการเก็บข้อมูลด้วย Service

การสร้าง Service ที่ใช้ในการจัดการข้อมูลต่าง ๆ ใน App ของเราใช้ Tutorial Guide จาก https://angular.io/start/data
ใน App ของเรานั้นจำเป็นต้องมี Service เอาไว้ใช้งาน เราสามารถใช้ในการจัดการข้อมูล และดึงข้อมูลจากแหล่งข้อมูลอื่น ๆ ผ่านทาง Service ได้ สำคัญมาก

สร้าง Service ชื่อ CartService ไว้เก็บข้อมูลการสั่งซื้อมือถือ ให้ใช้คำสั่ง "ng generate service cart" เสร็จแล้วเราจะได้ไฟล์มา 2 ไฟล์
1. "src/app/cart.service.spec.ts" และ 2. "src/app/cart.service.ts" เราจะเข้ามาแก้ไฟล์ที่ 2. นี่กัน
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class CartService {

  constructor() { }
}

ให้เราเพิ่ม Function 3 ตัวคือ addItem() ใช้เพิ่ม Item ลงตะกร้า , getItems() เรียกดูค่า Item ในตะกร้า และ clearItems() ลบ Item ออกจากตะกร้าทั้งหมด
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class CartService {

  items = [];

  addItem(product) {
    this.items.push(product);
  }

  getItems() {
    return this.items;
  }

  clearItems() {
    this.items = [];
  }

  constructor() { }

}

วันจันทร์ที่ 6 มกราคม พ.ศ. 2563

Angular 8 - แบ่ง Component เป็นหน้า ๆ กับ Router Module

ความเดิมจากตอนที่แล้วเราได้ทำการ Follow Guide หัวข้อ Your First App เสร็จแล้ว https://angular.io/start
ให้หัวข้อต่อมาเรื่องของ Routing https://angular.io/start/routing จะเริ่มสร้างหน้าย่อ ๆ กัน

ใช้ Code ต่อจากตอนที่แล้วเราจะทำการเพิ่ม RouterModule อย่างเดียวแล้วทำความเข้าใจกันก่อนว่ามันเป็นส่วนไหน
ให้เราทำการ Import Module ชื่อ "RouterModule" และทำการ Import และใส่ข้อมูล Path ด้วยใน "RouterModule.forRoot([])"
ส่วนของ path ใช่เป็น ' ' หมายถึง Root และแสดง Component ProductListComponent
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { RouterModule } from '@angular/router';

import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';


@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }
<app-top-bar></app-top-bar>
<app-product-list></app-product-list>

<router-outlet></router-outlet>

วันเสาร์ที่ 4 มกราคม พ.ศ. 2563

Angular 8 - สร้าง Component ใน Component ไปอีก

สร้างปุ่ม Notify Me เป็นแล้วเรียกใช้ใน Product List โดยจะสร้างเป็น Component และมีการรับค่าด้วย


เริ่มด้วยการสร้าง Component ชื่อ product-alerts อย่าลืมใช้คำสั่ง ng generate component product-alerts
แล้วเพิ่มปุ่ม Notify Me ใน Template
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-product-alerts',
  templateUrl: './product-alerts.component.html',
  styleUrls: ['./product-alerts.component.css']
})
export class ProductAlertsComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}
<p>
    <button>Notify Me</button>
</p>

วันพฤหัสบดีที่ 2 มกราคม พ.ศ. 2563

Angular 8 - สร้าง Event กับ Component และ เงื่อนไขในการแสดงผล

หัวข้อที่แล้วเราได้รู้จักกับ *ngFor, Interpolation {{ }} และ Property Binding [ ] ไปแล้ว
ในส่วนที่เราจะมาทำความรู้จักกับอีก 2 ตัวคือ *ngIf และ Event Binding ( ) กัน

พาทนี้ยังอยู่กับ https://angular.io/start ครับ โดยจากภาพแล้วเราจะทำการแสดง Description ออกมา
ส่วน Product ไหนไม่มี Description เราก็จะไม่แสดง

วันอังคารที่ 31 ธันวาคม พ.ศ. 2562

Angular 8 - ข้อมูล Static กับ Component และ การแสดงผล

การเก็บข้อมูล Static เป็น Hard Code และการเอาออกมาแสดงที่ Component
เรายังทำตาม Tutorial Your First App ส่วนนี้จะเป็นเกี่ยวกับข้อมูลที่เก็บไว้ใน App ของเราโดยเป็นแบบ Static
เว็บหน้า Your First App https://angular.io/start


ในไฟล์ Component เวลาที่เราประกาศตัวแปรในการเก็บข้อมูลเราสามารถตั้งชื่อขึ้นมาได้เลยในไฟล์ "product-list.component.ts"

โดยสร้างตัวแปร "title" เก็บคำว่า "Product List" ก็เพิ่มลงไปใน Code เป็น title='Product List'; ตามตัวอย่าง
เมื่อต้องการเรียกออกมาแสดงโดยเรียกใน Template ให้ใช้ {{ }} ในการเรียก เป็น {{title}} ก็จะดึงค่ามาแสดง

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})

export class ProductListComponent implements OnInit {

  title = 'Product List';

  constructor() { }

  ngOnInit() {
  }

}
<h1>{{title}}</h1>

วันเสาร์ที่ 28 ธันวาคม พ.ศ. 2562

Angular 8 - Tutorial Your First App กับการสร้าง Component

ตัวอย่าง App แรกของ Tutorial อ่านได้จาก https://angular.io/start
เราจะเริ่มสร้าง Component โดยใช้ Tutorial Your First App เป็น Guide

โดยขั้นแรกเราจะทำ Title แล้วก็ปุ่ม Cart พร้อมกับ Product 1 บรรทัดตามรูป

เริ่มโดยใช้คำสั่ง ng generate component [component-name]
ng generate component top-bar
ng generate component product-list