ionic material ศึกษาจาก demo เข้าใจการทำงานของ state ตอนที่ 1

เขียนเมื่อ 7 ปีก่อน โดย Ninenik Narkdee
ionicframework ionicmaterial

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ ionicframework ionicmaterial

ดูแล้ว 5,905 ครั้ง


เนื้อหานี้ต่อจากตอนที่แล้ว
ศึกษาและใช้งาน ionic material จาก demo เบื้องต้น 
 
จริงๆ แล้วเนื้อหาส่วนนี้จะมีอยู่ในบทความเก่า เกี่ยวกับ navigation และ template
การใช้งาน navigation ใน ionicframework ตอนที่ 5 
 
สามารถย้อนกลับไปศึกษาเพิ่มเติมได้ แต่ในที่นี้
เราจะทำการศึกษาาจากไฟล์ demo ว่ามีการทำงาน การประยุกต์ และมีรูปแบบที่น่า
เอามาต่อยอดได้เป็นอย่างไรบ้าง
 
มาดูโครงสร้างของ demo จากเนื้อหาตอนที่แล้ว
 
 
จากรูป  เราจะสนใจในส่วนของไฟล์ app.js controller.js 
และก็ไฟล์ในส่วนของ template 
 
ไฟล์ app.js ตัด comment ออก
 
 
angular.module('starter', ['ionic', 'starter.controllers', 'ionic-material', 'ionMdInput'])

.run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
        if (window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if (window.StatusBar) {
            StatusBar.styleDefault();
        }
    });
})

.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
    $ionicConfigProvider.views.maxCache(0);

    $stateProvider.state('app', {
        url: '/app',
        abstract: true,
        templateUrl: 'templates/menu.html',
        controller: 'AppCtrl'
    })

    .state('app.activity', {
        url: '/activity',
        views: {
            'menuContent': {
                templateUrl: 'templates/activity.html',
                controller: 'ActivityCtrl'
            },
            'fabContent': {
                template: '<button id="fab-activity" class="button button-fab button-fab-top-right expanded button-energized-900 flap"><i class="icon ion-paper-airplane"></i></button>',
                controller: function ($timeout) {
                    $timeout(function () {
                        document.getElementById('fab-activity').classList.toggle('on');
                    }, 200);
                }
            }
        }
    })

    .state('app.friends', {
        url: '/friends',
        views: {
            'menuContent': {
                templateUrl: 'templates/friends.html',
                controller: 'FriendsCtrl'
            },
            'fabContent': {
                template: '<button id="fab-friends" class="button button-fab button-fab-top-left expanded button-energized-900 spin"><i class="icon ion-chatbubbles"></i></button>',
                controller: function ($timeout) {
                    $timeout(function () {
                        document.getElementById('fab-friends').classList.toggle('on');
                    }, 900);
                }
            }
        }
    })

    .state('app.gallery', {
        url: '/gallery',
        views: {
            'menuContent': {
                templateUrl: 'templates/gallery.html',
                controller: 'GalleryCtrl'
            },
            'fabContent': {
                template: '<button id="fab-gallery" class="button button-fab button-fab-top-right expanded button-energized-900 drop"><i class="icon ion-heart"></i></button>',
                controller: function ($timeout) {
                    $timeout(function () {
                        document.getElementById('fab-gallery').classList.toggle('on');
                    }, 600);
                }
            }
        }
    })

    .state('app.login', {
        url: '/login',
        views: {
            'menuContent': {
                templateUrl: 'templates/login.html',
                controller: 'LoginCtrl'
            },
            'fabContent': {
                template: ''
            }
        }
    })

    .state('app.profile', {
        url: '/profile',
        views: {
            'menuContent': {
                templateUrl: 'templates/profile.html',
                controller: 'ProfileCtrl'
            },
            'fabContent': {
                template: '<button id="fab-profile" class="button button-fab button-fab-bottom-right button-energized-900"><i class="icon ion-plus"></i></button>',
                controller: function ($timeout) {
                }
            }
        }
    })
    ;
    $urlRouterProvider.otherwise('/app/login');
});
 
 
จะอธิบายและศึกษาเฉพาะส่วน หากใครเริ่มต้นศึกษา แนะนำให้อ่านบทความเกี่ยวกับ ionicframework 
ในตอนต้นๆ ก่อนเพื่อความเข้าใจ
 
angular.module('starter', ['ionic', 'starter.controllers', 'ionic-material', 'ionMdInput'])
 
โค้ดส่วนนี้ เป็นการลงทะเบียนและเรียกใช้ angular modules
starter คือ ชื่อ module ที่เรากำหนดในไฟล์ index.html 
 
<body ng-app="starter">
    <ion-nav-view></ion-nav-view>
</body>
 
สวน starter.controllers คือ ชื่อ module ที่เรียกใช้จากไฟล์ controllers.js
 
/* global angular, document, window */
'use strict';

angular.module('starter.controllers', [])
..........
 
ส่วนค่าอื่นๆ ที่เหลือก็เป็นชื่อ module ที่เรามีการใช้งานร่วมกับ app ของเรา
ได้แก่ ionic , ionic-material , ionMdInput
 
 
โค้ดส่วนต่อมา 
 
.run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
        if (window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if (window.StatusBar) {
            StatusBar.styleDefault();
        }
    });
})

 
โค้ดส่วนนี้ให้ข้ามไปก่อน เรายังไม่สนใจ
 
ส่วนที่เราให้ความสนใจ และต้องการศึกษาในตอนนี้คือส่วนของ 
 
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
    $ionicConfigProvider.views.maxCache(0);

    $stateProvider.state('app', {
        url: '/app',
        abstract: true,
        templateUrl: 'templates/menu.html',
        controller: 'AppCtrl'
    })

    .state('app.activity', {
        url: '/activity',
        views: {
            'menuContent': {
                templateUrl: 'templates/activity.html',
                controller: 'ActivityCtrl'
            },
            'fabContent': {

.........
....
..

    $urlRouterProvider.otherwise('/app/login');
});
 
สำหรับโค้ดในส่วนนี้ เหมือนการวางโครงสร้างว่า app ของเราจะมีหน้าไหนบ้าง 
state ก็เหมือนส่วนของตำแหน่งของการแสดง app ของเรา เช่น
state เริ่มต้นชื่อว่า app มื child state เป้น app.activity และอื่นๆ
 
เรามาดูว่าโค้ดตัวอย่างของเรามี state อะไรบ้าง 
- ส่วนแรกสุดเป็น parent state ชื่อ ว่า app
- ส่วนทีสองเป็น child state ได้แก่ activity ,friends, gallery, login, profile
เวลากำหนดเราจะใช้รูปแบบ parent.child ตัวอย่างถ้าเป็น state activity
ก็จะกำหนดได้เป้น app.activity แบบนี้เป็นต้น
 
ส่วนต่อไปเรามาดู url หรือก็ส่วนที่แสดงบน address bar ของแต่ละ state
 
    $stateProvider.state('app', {
        url: '/app',
        abstract: true,
        templateUrl: 'templates/menu.html',
        controller: 'AppCtrl'
    })

    .state('app.activity', {
        url: '/activity',
    })

    .state('app.friends', {
        url: '/friends',
    })

    .state('app.gallery', {
        url: '/gallery',
    })

    .state('app.login', {
        url: '/login',
    })

    .state('app.profile', {
        url: '/profile',
    })
    ;
    $urlRouterProvider.otherwise('/app/login');
 
 
รูปแบบก็จะเป้น '/ชื่อ state' เช่นถ้าเราเปิดหน้า app ไปที่หน้า profile
url  ที่แสดงบน address bar ก็จะเป้น #/app/profile
 
สังเกตว่า prfile จะเป็น child state ของ app ที่เป็น parent state
url ของ app ที่เป็น parent state คือ '/app'
url ของ profile ที่เป็น child state คือ '/profile'
url ของ address bar ของ app.profile state ก็จะได้เป้น #/app/profile แบบนี้เป็นต้น
(# คือรูปแบบการจัดการ url ของ  hybrid app ซึ่งจะต่างกับรูปแบบเว็บทั่วไป ต่อไปจะขอละ # มีพิมพ์แสดง
ให้เข้าใจว่าจะมี # นำหน้าเสมอ)
 
ต่อมา มาดูในส่วนของ parent state
 
    $stateProvider.state('app', {
        url: '/app',
        abstract: true,
        templateUrl: 'templates/menu.html',
        controller: 'AppCtrl'
    })

 
จะมีส่วนของการกำหนด abstract ,templateUrl: และ controller
abstract: true, ก็คือกำหนดให้ parent state นี้มีสถานะเป็น abstract state
Abstract state นี้จะไม่ถูกใช้งานหรือ activated ด้วมันเอง ซึ่งก็คือ เราไม่สามารถเรียกใช้งาน
ผ่าน /app ปกติเพื่อให้ state นี้ทำงานได้ แต่ state นี้จะถูกใช้งานอัตโนมัติเมื่อ child state ถูกเรียกใช้
เช่นเมื่อเรียกใช้งาน /app/profile ซึ่งเป็น child state ดังนี้แล้ว app ชื่อเป็น parent state ก็จะถูก
เรียกใช้งานในทางอ้อมไปด้วย โดยมีการเรียกไฟล์ template มาใช้งานและสร้าง ชื่อ controller
ดังนั้น เมื่อเรามีการเรียกใช้งาน /app/profile
ก็จะไปดึงรูปแบบการแสดงผลจากไฟล์ menu.html ผ่าน  templateUrl
 
        templateUrl: 'templates/menu.html',
 
และก็มีการสร้าง controller ชื่อ AppCtrl ขึ้นผ่าน 
 
        controller: 'AppCtrl'
 
 
ต่อไปเรามาดูส่วนของ child state จะสังเกตเห็นว่า รูปแบบการใช้งานก็จะคล้ายกัน
เปลี่ยนค่าไปตามส่วนที่กำหนด ขอยกมาสัก state มาอธิบาย 
 
    .state('app.activity', {
        url: '/activity',
        views: {
            'menuContent': {
                templateUrl: 'templates/activity.html',
                controller: 'ActivityCtrl'
            },
            'fabContent': {
                template: '<button id="fab-activity" class="button button-fab button-fab-top-right expanded button-energized-900 flap"><i class="icon ion-paper-airplane"></i></button>',
                controller: function ($timeout) {
                    $timeout(function () {
                        document.getElementById('fab-activity').classList.toggle('on');
                    }, 200);
                }
            }
        }
    })
 
แยกมาดูส่วนของ views
 
    .state('app.activity', {
        url: '/activity',
        views: {
            'menuContent': {

            },
            'fabContent': {

            }
        }
    })
 
views ของแต่ละ state ก็คือ ส่วนของการแสดงข้อมูลซึ่งเราสามารถแยกย่อยไปแต่ละส่วนได้
เรากลับไปดูที่ไฟล์ menu.html ที่เป็น template แรกที่ถูกโหลดมาใช้งาน โดยดูโครงสร้าง app  ประกอบ
ตามรูป
 
     
 
 
ดูโค้ดไฟล์ menu.html ประกอบ
 
<ion-side-menus enable-menu-with-back-views="true">
    <ion-side-menu-content>
        <ion-nav-bar class="bar-assertive-900" ng-class="{expanded: isExpanded, 'has-header-fab-left': hasHeaderFabLeft, 'has-header-fab-right': hasHeaderFabRight}" align-title="left">
<!--	ส่วนหัวของ app หรือส่วนของ bar จากรูปด้านบนก็จะเป้นส่วนขอกรอบงสี่เหลี่ยมสีเหลือง-->
        </ion-nav-bar>
        <ion-nav-view name="fabContent">
<!--        ส่วนของไอค่อนเมนูย่อย ส่วนของกรอบสีเขียวและฟ้า-->
        </ion-nav-view>
        <ion-nav-view name="menuContent" ng-class="{expanded: isExpanded}" >
<!--      	  เนื้อหาของ app จะแสดงในส่วนนี้ ส่วนของกรอบสีม่วง-->
        </ion-nav-view>
    </ion-side-menu-content>
    
    <ion-side-menu side="right"><!-- ส่่วนของ เมนูด้านขวา ส่วนของกรอบสีชมพู -->
        <ion-header-bar class="dark-bg expanded">
<!--			ส่วนหัวหรือ bar ของเมนูด้านขวา-->
        </ion-header-bar>
        <ion-content class="stable-bg has-expanded-header">
<!--			เนื้อหาของเมนูด้านขวา-->
        </ion-content>
    </ion-side-menu>
</ion-side-menus>
 
รูปแบบของ app demo จะเป็นแบบเมีเมนูด้านขวา ใช้งาน ion-side-menu
และมีแท็บ subheader พร้อมปุ่มไอคอน ขอแยกให้ดูง่ายขึ้น
 
<ion-side-menus enable-menu-with-back-views="true">
    <ion-side-menu-content>
<!--			เนื้อหาตรงกลางของ app กรอบสีม่วง -->
    </ion-side-menu-content>
    <ion-side-menu side="right"><!-- ส่่วนของ เมนูด้านขวา กรอบสีชมพู-->
<!--			เนื้อหาของเมนูด้านขวา-->
    </ion-side-menu>
</ion-side-menus>
 
 
ขอจบส่วนของตอนนี้ไว้แค่นี้ก่อน ดูต่อในเนื้อหาตอนหน้า

 


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ







เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ