跳到主要內容

Angularjs:動態Render 控制項


當我們在設計表單頁面時,常常會發現許多控制項都是常見的,尤其是開發多個頁面時,那麼假設開發完第一頁之後勢必又要將寫過的程式碼搬移到第二頁,造成冗於的代碼,如果我們能將這些控制項進行預製設計,而後便由後端所提供的資料來動態產生控制項,如此一來前端不僅減少冗於代碼,重要的業務邏輯也能由後端控制,乾淨切割相關責任,更易於管理,那麼在Angularjs中我們可以將預設樣板設計於directive或者使用ng-include動態載入樣板,但其中會發現一個問題點是,我們必須要有一個可以判斷該資料依據,才能將資料套用到正確的樣板,那麼剩下的就只剩後端資料的解析,在下面的範例中簡單的預置三個樣板,分別為textbox、selection、textarea。

一、範例網址: http://plnkr.co/edit/GJeKuz?p=info


二、首先我們假設後端給出的json資料
     (一)render.json,在這邊只需要抓出"rel" = "section"的連結,再根據此連結去獲取render的資料內容

{
    "collection":{
        "version": "1.0",
        "href": "http://localhost/multiTemplate",
        "links": [
            {
                "rel": "section",
                "prompt": "RenderA",
                "href": "renderA.json"
            },
            {
                "rel": "section",
                "prompt": "RenderB",
                "href": "renderB.json"
            },
            {
                "rel": "section",
                "prompt": "RenderC",
                "href": "renderC.json"
            },
            {
                "rel": "creator",
                "href": ""
            }
        ],
        "items":[]
    }
}

   (二)分別假設renderA、B、C的片段資料為:
          1.renderA,textbox的資料結構:

{
    "collection": {
        "version": "1.0",
        "href": "",
        "links":[],
        "items": [
            {
                "data": [
                    {
                        "name": "名字",
                        "value": "王曉明",
                        "prompt": "textbox"
                    }
                ]
            }
        ]
    }
}

          2.renderB,selection的資料結構:

{
    "collection": {
        "version": "1.0",
        "href": "",
        "links":[],
        "items": [
            {
                "data": [
                    {
                        "name": "性別",
                        "array": [
                            {
                                "name": "男"
                            },
                            {
                                "name": "女"
                            }
                        ],
                        "prompt": "selection"
                    }
                ]
            }
        ]
    }
}

          3.renderC,textarea的資料結構

{
    "collection": {
        "version": "1.0",
        "href": "",
        "links":[],
        "items": [
            {
                "data": [
                    {
                        "name": "自我介紹",
                        "value": "............",
                        "prompt": "textarea"
                    }
                ]
            }
        ]
    }
}

三、利用Angularjs中的directive來設計預置樣板,並進行資料的綁定

(function(){
    angular.module("multiTemp")
        .directive("dynamicControl",["$compile",dynamicControl])
    function dynamicControl($compile){
        var textboxTemplate = "{{data.name}} : <input type='text' class='form-control' ng-model='data.value' />";
        var selectionTempate = "<label>{{data.name}}</label><select class='form-control'><option ng-repeat='sex in data.array'>{{sex.name}}</option></select>";
        var textareaTemplate = "<label>{{data.name}}</label><textarea class='form-control' row='5' ng-model='data.value'></textarea>"
        var templateMapping = {
            "textbox": textboxTemplate,
            "selection": selectionTempate,
            "textarea": textareaTemplate
        }
        function linker(scope, element, attrs){
            element.html(templateMapping[scope.data.prompt]).show();
            $compile(element.contents())(scope);
        }
        return{
            restrict: "E",
            link: linker,
            scope:{
                data: "="
            }

        }
    }
})()

四、設計取得json的http服務

(function(){
    angular.module('jsonMethodModule',[])
        .service('jsonMethodService',function($q,$http){
            var getJson = function(url){
                var deferred = $q.defer();
                $http.get(url).success(function(data,status, headers, config){
                    deferred.resolve(data);
                }).error(function (data, status, headers, config){
                    deferred.reject(data);
                });
                return deferred.promise;
            }
            return{
                getJson: getJson
            };
        })
})();

五、設計剖析json的服務

(function () {
    angular.module('jsonParseModule', [])
        .service('jsonParseService', jsonParseService)
   function DataClass(name, value,array, prompt, href) {
        this.name = name;
        this.value = value;
        this.array = array;
        this.prompt = prompt;
        this.href = href;
    }
    function jsonParseService() {
        function getDatasFromCollectionJson(collectionJson) {
            var datas = new Array()
            angular.forEach(collectionJson.collection.items, function (item) {
                angular.forEach(item.data, function (detailItem) {
                    var data = new DataClass(detailItem.name, detailItem.value,detailItem.array, detailItem.prompt, item.href)
                    datas.push(data);
                });
            })
            return datas;
        }
        function getRelTemplate(links,rel){
            var result = [];
            angular.forEach(links,function(link){
                if (link.rel == rel) result.push(link);
            })
            return result;
        }
        return{
            getDatasFromCollectionJson: getDatasFromCollectionJson,
            getRelTemplate: getRelTemplate
        };
    }
})();

六、設計controller,首先取得render.json後再篩選出links中rel = section的項目,再分別根據各個項目的的連結取得資料內容。

(function(){
    angular.module('multiTemp',['jsonParseModule','jsonMethodModule'])
        .controller('multiTempCtrl',['jsonMethodService','jsonParseService','$http',multiTempCtrl])
    function multiTempCtrl(jsonMethodService,jsonParseService,$http){
        var self = this;
        self.sections = [];
        setRenderData();

        function setRenderData(){
            jsonMethodService.getJson('json/render.json').then(function(collectionjson){
                self.sections = jsonParseService.getRelTemplate(collectionjson.collection.links,"section");
                angular.forEach( self.sections,function(section){
                    jsonMethodService.getJson('json/' + section.href).then(function(collectionjson){
                        var datas = jsonParseService.getDatasFromCollectionJson(collectionjson);
                        section.datas = datas;
                    })
                })
            })
        }
    }
})();

七、將資料綁定到index.html並使用directive進行動態控制項的產生:

<!DOCTYPE html>
<html ng-app="multiTemp">

  <head>
    <link data-require="bootstrap@3.3.2" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
    <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script data-require="bootstrap@3.3.2" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script data-require="angular.js@1.4.0" data-semver="1.4.0" src="https://code.angularjs.org/1.4.0/angular.js"></script>
    <script src="controllers/app.js"></script>
    <script src="services/jsonMethod.js"></script>
    <script src="services/jsonParse.js"></script>
    <script src="directives/directive.js"></script>
  </head>

  <body ng-controller="multiTempCtrl as tempCtrl">
    <div ng-repeat="section in tempCtrl.sections">
        <div class="panel">
            <div class="panel-heading">{{section.prompt}}</div>
        </div>
        <div class="panel-body">
            <div ng-repeat="data in section.datas">
                <dynamic-control data="data"></dynamic-control>
            </div>

        </div>
    </div>
</body>
</html>

留言

這個網誌中的熱門文章

java西元民國轉換_各種不同格式

C#資料庫操作(新增、修改、刪除、查詢)

【Excel好好玩】 自己的資產自己管!善用Google Sheet來幫我們評估貸款

這次介紹的主題是關於Excel的貸款還款計畫試算,我們人生中總會遇到需要大筆金額的花費,但當資金不夠時就得進行貸款,而貸款之前如果我們能夠審慎評估,並分析自己的還款能力之後在進行凍作,相信風險會小很多,因此就自己動動手來使用Google Sheet進行試算吧! 基本資料 ● 貸款總額: 1000000 ● 貸款期數: 84月 ● 年利率: 2.11% ● 月利率: 0.18% P.S 月利率 = 年利率 / 12 重要函式 PMT : 這是Google Sheet內建的重要年金計算公式,我們可以善用這個公式來計算固定利率及期數的固定攤還本息。因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 動手做 首先我們在Excel表上列出我們的基本資料 圖片來源 其中月利率的部分就使用公式「=B4/12」 接著我們填上第一列的期數跟餘額 圖片來源 =B2 =B3 使用關鍵PMT函數來計算本息的部分 因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 -PMT(貸款利率(月利率), 貸款期數, 貸款總額) =-PMT($B$5,$B$3,$B$2) 圖片來源 計算利息 利息 = 貸款餘額 x 月利率 =B8*$B$5 圖片來源 計算本金 本金 = 本息 - 利息 =C8-D8 圖片來源 製作第二列餘額的部分 餘額的部分 = 上一期的餘額 - 上一期的本金 圖片來源 接著拖曳該兩列往下拉,即可查看每一期的利息與本金 圖片來源 結語 雖然市面上已經有很多貸款銀行都提供了試算功能,但如果我們想要進一步管理自己的資產時,就需要將每一期的金額給計算出來,因此才會將公式運用在Excel表,讓我們的資產管理表能夠結合負債,進一步評估我們理財行動的下一步,希望這樣的經驗可以幫助到正在理財道路上打拼的夥伴,讓我們透過有效的管理,幫助荷包長大吧! 喜歡撰寫文章的你,不妨來了解一下: Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 — 為什麼要加入? 歡迎加入一起練習寫作,賺取知識,累積財富!