Angularjs组件数据未传递给控制器​​

时间:2017-01-02 19:54:30

标签: javascript angularjs

在假期休假之后,我有些打破了我之前建立的角色组件。

这是一个用于测试的JS小提琴的链接:https://jsfiddle.net/mvalli/nr4q0q0o/14/

由于某种原因,'items''panel-format'属性未将提供的值传递给它们之前的组件控件。我一直在努力找到我的错误并且可以使用第二组眼睛,因为它已经阻止我继续开发我正在添加的分页和排序功能。

注意: 在我尝试调试时,我添加了<div>products: {{ products }}</div>,它显示了从ProductListController传递的JSON数组产品,其中包含<list-panel items="..." panel-format="..."></list-panel>标记从父视图。

我将变量products应用到我$scope的{​​{1}}变量后,也会在控制台中记录变量ProductListController并获得成功结果。我尝试通过将ListController$scope.items变量都记录到控制台来检查数据是否已传递到组件this.items,结果为undefined两者(正确的)变量应该是this.items但我想检查$scope.items,以防我在Angular中缺少具有隔离范围的概念。)

列表panel.module.js

var listPanelModule = angular.module("listPanel", []);

列表panel.component.js

angular.module("listPanel")
        .component("listPanel", {
    bindings: {
        "items": "<",
        "panelFormat" : "<"
    },
    controller: "ListController",
    templateUrl: "js/modules/list-panel/list-panel.template.html"
});

用法:product-list.html

<div>products: {{ products }}</div>
<list-panel items='products' panel-format="listPanelFormat"></list-panel>

组件控制器:ListController.js

/* 
 * ListController.js
 * 
 * Used to manage the list-component data attributes.
 * 
 * @author mvalli
 */

console.log("Setting up the list-panel.controller.js...");
angular.module('listPanel')
        .controller("ListController", ['$scope', '$filter', function($scope, $filter) {
    // LOGGER
    this.CLASSNAME = "ListController";
    this.TESTING = true;

    // CONSTANTS
    console.log("onInit items: ", this.items);
    console.log("onInit scope.items: ", $scope.items);
    // PROPERTIES
    // Filtering
    this.query;
    this.orderProp;
    // Ordering
    this.sort = {       
        sortingOrder : 'name',
        reverse : false
    };
    // Item Tracking
    this.pageSize = 10;
    this.currentHeadRecord = 0;
    this.currentTailRecord = this.currentHeadRecord + this.pageSize;
    // Page Tracking
    this.currentPage = 0;
    this.lastPage = 0;
    this.pagingButtonCount = 5;
    // Data Structures
    this.items;// JSON Object of the List Data/Content
    this.filteredItems = [];
    this.groupedItems = [];
    this.pagedItems = [];

    // Segmented View Button
    this.selectListView = false;
    this.selectGalleryView = true;

    // FORMATTING
    this.panelFormat;   // JSON Object of the List Structure (i.e. Fields to display, order to display, any callbacks)
    /*
     * EXAMPLE - listData:
        {
            "_embedded" :   {
                                "customers" : [
                                    {   "firstName" : "Matt",
                                        "lastName" : "Valli",
                                        "age" : 29,
                                        "_links" : {
                                            self: "..."
                                        }
                                    },
                                    {   "firstName" : "Paul",
                                        "lastName" : "Kay",
                                        "age" : 40
                                    },
                                    {   "firstName" : "Paul",
                                        "lastName" : "Kay",
                                        "age" : 40          
                                    }
                                ]
                            }
            }

     * EXAMPLE - listFormat:
        {
            "headerLabel" : "Cloud Reseller",
            "controller" : ServiceProviderController,
            "templateUrl" : "js/modules/list-panel/list-panel.html",
            "list" : {
                "templateUrl": "views/serviceProvider/list-serviceProvider.html",
                },
            "gallery" : {
                "templateUrl": "views/serviceProvider/gallery-serviceProvider.html",
            }
            "displayOrder" :    [   
                                    {   "data" : _embedded.serviceProviders.name,
                                        "label" : "Service Provider Name",
                                        "link" : {  "url": _embedded.cloudReseller._links.
                                                    "method": "GET"                         },

                                    {   "data" : _embedded.customers.lastName,
                                        "label": "Last Name"        
                                        "sortable" : true                       },

                                    {   "data" : _embedded.customers.age
                                        "label" : "Age"             
                                        "sortable" : true                       }
                                ],
            // BUTTON FEATURES
            "rowControls" : [   
                                {   "label": "Edit",
                                    "templateUrl": "/controlButtons/edit",
                                    "display" : true,
                                    "link" : {  _embedded.customers._link.self,
                                                "method" : "GET,
                                                route: "/serviceProvider/1/edit" }
                                    "callback" : "" },

                                {   "label": "View Customers",
                                    "display": true,
                                    "link" : _embedded.customers._links.customers
                                    "callback" : ""
                                }
                            ]
            "rowDeleteButton" : false,              
            "listExportable" :  true
        }
     * 
     */



    // Methods
    /**
     *  Changes the view in the List Panel to the List View.
     */
    this.showListView = function() {
        console.log(this.CLASSNAME + ".showListView()");
        // Update Selected View
        this.selectListView = true;
        this.selectGalleryView = false;
        console.log(this.CLASSNAME + ".selectListView: ", this.selectListView);
    };

    /**
     * Changes the view in the List Panel to the Gallery View.
     */
    this.showGalleryView = function() {
        console.log(this.CLASSNAME + ".showGalleryView()");
        // Update Selected View
        this.selectListView = false;
        this.selectGalleryView = true;
        console.log(this.CLASSNAME + ".selectGalleryView: ", this.selectGalleryView);
    };

    /*
     * Updates the Displays based on a change in using the controls.
     */
    this.updateDisplay = function() {
        console.log(this.CLASSNAME + ".updateDisplay()");
        this.currentTailRecord = parseInt(this.currentHeadRecord) + parseInt(this.pageSize);
    };

    /**
     * Uses the panelFormat to determine how many columns there are in the table.
     */
    this.getTableWidth = function() {
        console.log(this.CLASSNAME + ".getTableWidth()");
        var width = 0;
        if (this.panelFormat.displayColumns != null) {
            width = this.panelFormat.displayColumns.length;
        }
        return width;
    };

    /**
     * Returns true if an item matches the matcher in the collection,
     * false if no item matches the matcher.
     * 
     */
    var searchMatch = function (collection, matcher) {
        if (!matcher) {
            return true;
        }
        return collection.toLowerCase().indexOf(matcher.toLowerCase()) !== -1;
    };

    /**
     * Lifecycle: init
     * 
     * Sorts the items remaining after applying a search filter. An empty search
     * filter sorts the complete collection of items.
     * 
     */
    // init the filtered items
    this.search = function () {
        console.log("onSearch items: ", this.items);
        // Creates an array of items that match the provided anonymous 'compareTo' function
        this.filteredItems = $filter('filter')(this.items, function (item) {
            // Loop through the attributes of an Item
            for(var currentAttribute in item) {
                // If the currentAttribute in the item matches the Search Query
                if (searchMatch(item[currentAttribute], this.query))
                    // Reflect a Match
                    return true;
            }
            // Reflect a Mismatch
            return false;
        });
        // Reorder the items based on the sorting order
        if (this.sort.sortingOrder !== '') {
            // Order the Filtered Items by the sortingOrder
            this.filteredItems = $filter('orderBy')(this.filteredItems, this.sort.sortingOrder, this.sort.reverse);
        }
        // Ensure the user lands on the first page of the results
        this.currentPage = 0;
        // Generate the Pages based on the Panel Settings
        this.groupToPages();
    };

    /**
     * Creates a collection of sub-arrays sized by pageSize
     * 
     */
    this.groupToPages = function () {
        // Reset the pagedItems collection to an empty array to create a clean page grouping
        this.pagedItems = [];
        // Loop through all of the Filtered Items
        for (var i = 0; i < this.filteredItems.length; i++) {
            // If the current 'i' returns 0 from a modulus operator
            if (i % this.pageSize === 0) {
                // Create a new page/collection with the item and add it to the collection of pages
                this.pagedItems[Math.floor(i / this.pageSize)] = [ this.filteredItems[i] ];
            } else {
                // Add the current item to an existing page collection
                this.pagedItems[Math.floor(i / this.pageSize)].push(this.filteredItems[i]);
            }
        }
    };

    /**
     * 
     * @param {type} numberOfPages - The length of the pagedItems.
     * @param {type} start - The initial page button to display.
     * @param {type} end - The last page button to display.
     * @returns {Array} - An array of page buttons.
     */
    this.range = function (numberOfPages, start, end) {
        // Create a collection of Paging Buttons to return
        var ret = [];
        // Log the Range for Debugging
        console.log(numberOfPages, start, end);

        // If the number of pages is less than the size
        if (numberOfPages < end) {
            // The last button should equal the size
            end = numberOfPages;
            // The first button should 
            start = numberOfPages - $scope.gap;
        }
        for (var i = start; i < end; i++) {
            // Add the buttons to the List of Buttons to display
            ret.push(i);
        }
        // Log the Results for debugging
        console.log(ret);        
        return ret;
    };

    /**
     * Moves the currentPage back an index in the pagedItems collection if not
     * on the first page.
     * 
     */
    this.prevPage = function () {
        if (this.currentPage > 0) {
            this.currentPage--;
        }
    };

    /**
     * Moves the currentPage forward an index in the pagedItems collection if not
     * on the last page.
     * 
     */
    this.nextPage = function () {
        if (this.currentPage < this.pagedItems.length - 1) {
            this.currentPage++;
        }
    };

    /**
     * Sets the current page to the selected Paging Button.
     */
    this.setPage = function () {
        $scope.currentPage = this.n;
    };

    // Processes the Data on initialization
    console.log("pre-search items: ", this.items);
    console.log("scope.items: ", $scope.items);
    this.search();
}]);

组件模板:list-panel.template.html

<!-- START DATATABLE EXPORT -->
<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">{{ $ctrl.panelFormat.headerLabel }}</h3>
        <div class="pull-right">
            <div class="btn-group" role="group" aria-label="...">
                <button type="button" class="btn btn-default" ng-click="$ctrl.showListView()" ng-selected="{{ $ctrl.selectListView }}"><span class="glyphicon glyphicon-list"></span>List</button>
                <button type="button" class="btn btn-default" ng-click="$ctrl.showGalleryView()" ng-selected="{{ $ctrl.selectGalleryView }}"><span class="glyphicon glyphicon-th"></span>Gallery</button>
            </div>

            <div class="btn-group">
                <button class="btn btn-danger dropdown-toggle" data-toggle="dropdown"><i class="fa fa-bars"></i> Export Data</button>
                <ul class="dropdown-menu">
                    <li><a href="#" onClick ="$('#products').tableExport({type:'json',escape:'false'});"><img src='img/icons/json.png' width="24"/> JSON</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'json',escape:'false',ignoreColumn:'[2,3]'});"><img src='img/icons/json.png' width="24"/> JSON (ignoreColumn)</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'json',escape:'true'});"><img src='img/icons/json.png' width="24"/> JSON (with Escape)</a></li>
                    <li class="divider"></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'xml',escape:'false'});"><img src='img/icons/xml.png' width="24"/> XML</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'sql'});"><img src='img/icons/sql.png' width="24"/> SQL</a></li>
                    <li class="divider"></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'csv',escape:'false'});"><img src='img/icons/csv.png' width="24"/> CSV</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'txt',escape:'false'});"><img src='img/icons/txt.png' width="24"/> TXT</a></li>
                    <li class="divider"></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'excel',escape:'false'});"><img src='img/icons/xls.png' width="24"/> XLS</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'doc',escape:'false'});"><img src='img/icons/word.png' width="24"/> Word</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'powerpoint',escape:'false'});"><img src='img/icons/ppt.png' width="24"/> PowerPoint</a></li>
                    <li class="divider"></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'png',escape:'false'});"><img src='img/icons/png.png' width="24"/> PNG</a></li>
                    <li><a href="#" onClick ="$('#products').tableExport({type:'pdf',escape:'false'});"><img src='img/icons/pdf.png' width="24"/> PDF</a></li>
                </ul>
            </div>
        </div>                                    

    </div>
    <div class="panel-controls col-md-12" style="padding-top: 10px;">
            <div class="form-group col-md-3 form-inline">
                <label for="pageSize">Show</label>
                <select id="pageSize" class="form-control" ng-model="$ctrl.pageSize" ng-change="$ctrl.updateDisplay()">
                    <option value="10">10</option>
                    <option value="25">25</option>
                    <option value="50">50</option>
                    <option value="100">100</option>
                </select>
            </div>
                <label for="numberRecordsToDisplay">Entries</label>

            <div class="form-group col-md-7">
                <input id="searchProducts" class="form-control" placeholder="Search" ng-model="$ctrl.query">
            </div>

            <div class="form-group col-md-2">
                <select id="sortProducts" class="form-control" ng-model="$ctrl.orderProp">
                    <option ng-selected="{{option.selected}}" value="{{option.id}}" ng-repeat="option in $ctrl.panelFormat.sortOptions">{{ option.name }}</option>
                </select>
            </div>
    </div>
    <div class="panel-body">

        <div class="row">
                <div id="list" ng-show="$ctrl.selectListView">
                    <div class="table-responsive col-md-12">
                        <table id="products" class="table table-striped table-hover">
                            <thead>
                                <tr>
                                    <th custom-sort order="'name'" sort="sort">Name</th>
                                    <th custom-sort order="'description'" sort="sort">Description</th>
                                    <th custom-sort order="'licenseQty'" sort="sort">License Qty</th>
                                    <th custom-sort order="'price.listPrice'" sort="sort">List Price</th>
                                    <th custom-sort order="'price.discountPrice'" sort="sort">Discount Price</th>
                                    <th custom-sort order="'savings'" sort="sort">Savings</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr ng-repeat="listItem in $ctrl.items | filter: $ctrl.query | orderBy: $ctrl.orderProp">
                                    <td>{{ listItem.name }}</td>
                                    <td>{{ listItem.description }}</td>
                                    <td>{{ listItem.licenseQty }}</td>
                                    <td>{{ listItem.price.listPrice | currency }}</td>
                                    <td>{{ listItem.price.discountPrice | currency }}</td>
                                    <td>{{ calculateSavings(listItem) | currency }}</td>
                                </tr>
                                <tr ng-if="$ctrl.items == null || $ctrl.items.length == 0">
                                    <td col-span="{{ $ctrl.getTableWidth() }}"><strong>No results found...</strong></td>
                                </tr>
                            </tbody>
                        </table>                                
                    </div>
                </div>
                <div id="gallery">
                    <div class="gallery" ng-show="$ctrl.selectGalleryView"><!-- gallery list -->
                        <!--<product-tile ng-repeat="product in $ctrl.products" data="product"></product-tile>-->
                        <a class="gallery-item {{ galleryItem.licenseQty }}" href="{{ $ctrl.route }}" ng-repeat="galleryItem in $ctrl.items | filter:$ctrl.query | orderBy:$ctrl.orderProp"><!-- gallery item -->
                            <div class="image"><!-- item image -->
                                <img src="assets/images/gallery/nature-1.jpg" alt="Nature Image 1">                                        
                                <ul class="gallery-item-controls"><!-- item controls -->                   
                                    <li><span class="gallery-item-remove"><i class="fa fa-times"></i></span></li><!-- controls item -->
                                </ul><!-- /item controls -->                                                                   
                            </div><!-- ./item image -->
                            <div class="meta"><!-- item description -->
                                <strong>{{ galleryItem.name }}</strong>
                                <span>Licenses included</span>
                                <p><strong><ng-pluralize count="galleryItem.licenseQty" when="$ctrl.panelFormat.pluralize.licenses"></ng-pluralize></strong></p>
                                <span>Price</span>
                                <p>Cost Price: {{ galleryItem.price.costPrice | currency }}<br>
                                    List Price: {{ galleryItem.price.listPrice | currency }}<br>
                                    Discounted Price: {{ galleryItem.price.discountPrice | currency }}<br>
                                    Total Savings: <span class="text-red">{{ calculateSavings(gallerItem) | currency }}</span>

                                </p>
                                <span>Description</span>
                                <p>{{ galleryItem.description }}</p>
                            </div><!-- ./item description -->                               
                        </a><!-- ./gallery item -->
                        <div ng-if="$ctrl.items == null || $ctrl.items.length == 0">
                            <strong>No results found...</strong>
                        </div>
                    </div><!-- ./gallery list -->
                </div>
        </div>
        <div class="col-med-12">
            <div class="col-md-6">
                Showing {{ $ctrl.startingRecord }} to {{ $ctrl.currentLast }} of {{ $ctrl.dataList.length }} entries
            </div>
            <div class="col-md-6">
                <nav class="pull-right" aria-label="Page navigation">
                    <ul class="pagination">
                        <li>
                            <a href="#" class="paginate_button previous"  aria-label="Previous">
                                <span aria-hidden="true">Previous</span>
                            </a>
                        </li>

                        <li><a class="paginate_button" href="#">1</a></li>
                        <li><a class="paginate_button" href="#">{{ (parseInt($ctrl.data.length) / parseInt($ctrl.pageSize)) }}</a></li>
                        <li>
                            <a href="#" class="paginate_button next" aria-label="Next">
                                <span aria-hidden="true">Next</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
    </div><!-- ./panel-body -->
</div>
<!-- END DATATABLE EXPORT -->

产品的JSON示例:

{
                "products": [
                        {
                            "id": 1,
                            "vendor" : 1,
                            "releaseDate": 1,
                            "price": 25.00,
                            "label" : "Microsoft Word",
                            "snippet" : "Document and Word Processing",
                            "description" : "Microsoft Word is the World-Leading Desktop Application for creating rich formatted documents.",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 2,
                            "vendor" : 1,
                            "releaseDate": 1,
                            "price": 25.00,
                            "label" : "Microsoft Excel",
                            "snippet" : "Spreadsheet Manager",
                            "description" : "Microsoft Excel is the World-Leading Spreadsheet Processing software for creating rich formatted documents.",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 3,
                            "vendor" : 1,
                            "releaseDate": 1,
                            "price": 25.00,
                            "label" : "Microsoft Powerpoint",
                            "snippet" : "Slideshow Presentation Manager",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 4,
                            "vendor" : 1,
                            "releaseDate": 1,
                            "price": 25.00,
                            "label" : "Microsoft Outlook",
                            "snippet" : "Email Manager",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 5,
                            "vendor" : 1,
                            "releaseDate": 2,
                            "price": 25.00,
                            "label" : "Microsoft OneNote",
                            "snippet" : "Cloud-based Document Manager",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 6,
                            "releaseDate": 5,
                            "price": 25.00,
                            "label" : "Microsoft Access",
                            "snippet" : "This Access Thing...",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 7,
                            "vendor" : 1,
                            "releaseDate": 2,
                            "price": 25.00,
                            "label" : "Microsoft Project",
                            "snippet" : "Project Management Tool",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 8,
                            "vendor" : 1,
                            "releaseDate": 3,
                            "price": 25.00,
                            "label" : "Microsoft Publisher",
                            "snippet" : "Content Layout Manager",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 9,
                            "vendor" : 1,
                            "releaseDate": 4,
                            "price": 25.00,
                            "label" : "Microsoft Visio",
                            "snippet" : "UML & Data Modeling Tool",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 10,
                            "vendor" : 1,
                            "releaseDate": 3,
                            "price": 25.00,
                            "label" : "Microsoft Sway",
                            "snippet" : "Side to Side",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 11,
                            "vendor" : 1,
                            "releaseDate": 5,
                            "price": 25.00,
                            "label" : "Microsoft Teams",
                            "snippet" : "Resource Manager",
                            "description" : "Blah, blah, blah",
                            "licenseQty" : 1,
                            "contents" : []
                        },
                        {
                            "id": 12,
                            "vendor" : 1,
                            "releaseDate": 1,
                            "price": 50.00,
                            "label" : "Microsoft Office 365",
                            "snippet" : "Lots of Apps!",
                            "description" : "This product includes 1 Licenses for Microsoft Office 365.",
                            "licenseQty" : 1,
                            "contents" : [
                                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
                            ]
                        },
                        {
                            "id": 13,
                            "vendor" : 1,
                            "releaseDate": 3,
                            "price": 150.00,
                            "label" : "Microsoft Office 365",
                            "snippet" : "Lots of Apps for All!",
                            "description" : "This product includes 5 Licenses for Microsoft Office 365.",
                            "licenseQty" : 5,
                            "contents" : [
                                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
                            ]
                        }
                ]
            }

0 个答案:

没有答案