0

I am new to Angular and am stuck on my next step of development which is to have a custom control bound to a dynamic row-column table.

I have a simple fiddle here which shows how to data bind a custom control:

http://jsfiddle.net/paull3876/WPWAc/2/

And another fiddle here which is my starting point, shows how to bind a row-column table with data driven column names:

http://jsfiddle.net/paull3876/3mz5L/1/

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <title>Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>

<script>

var app = angular.module("myApp", []);

function datacontroller($scope, $http)
{
    $scope.mydata = [{f1:"r1f1", f2:"r1f2"}, {f1:"r2f1",f2:"r2f2"}, {f1:"r3f1",f2:"r3f2", f3:"Hello"}];
    $scope.mycolumns = [{name:"Column 1", fieldname:"f1"}, {name:"Column 2", fieldname:"f2"}, {name:"Column 3", fieldname:"f3"}];

    $scope.showdata = function()
    {
        alert(JSON.stringify($scope.mydata));
    }

    $scope.getcolumnname = function(cell)
    {
        return cell.fieldname;
    }
}

</script>

</head>
<body>
    <div data-ng-controller="datacontroller">
        <table>
        <tr>
        <td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
        </tr>
        <tr data-ng-repeat="record in mydata">
        <td data-ng-repeat="cell in mycolumns">
        <input type="text" data-ng-init="mycol=getcolumnname(cell);" data-ng-model="record[mycol]" />
        </td>
        </tr>
        </table>

        <br />
        <input type="button" value="Save Data" ng-click="showdata()" />
        <br />
        <br />

    </div>

</body>
</html>

Now I want to take the second fiddle above, and replace the INPUT element with a user control which has two way data binding. I've spend a day on this already and can't get it working, so I guess I'm also needing some help on the concepts here

An explanation on top of a solution greatly appreciated.

http://jsfiddle.net/paull3876/rc7uC/1/

1

1 Answer 1

4

Here's the full working solution, I hope someone finds it useful.

<!DOCTYPE html>
<html >
<head>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="expires" content="-1">
    <title>Angular</title>
    <!--scr ipt src="htt ps://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script-->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js"></script>
</head>
<body>
    <div data-ng-app="myApp" data-ng-controller="datacontroller">
        <table>
            <tr>
                <td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
            </tr>
            <tr data-ng-repeat="record in mydata">
                <td data-ng-repeat="cell in mycolumns">
                    <mycontrol data-my-model="record[cell.fieldname]"></mycontrol>
                </td>
            </tr>
        </table>
        <br />
        <input type="button" value="Save Data" ng-click="showdata()" />
        <input type="button" value="Change Divs" onclick="changediv()" />
        <input type="button" value="Change Scope" onclick="changescope()" />
        <br />
        <br />
    </div>
</body>
</html>
<script>
    var globalscope;
    var app = angular.module("myApp", [])
        .directive("mycontrol", function ($compile) {
        return {
            restrict: "E",
            scope: {
                value: "=myModel"
            },
            template: "<div data-ng-bind='value'/>"
        };
    });

    function datacontroller($scope, $http) {
        globalscope = $scope;
        var mydata = [];
        // generate some data
        for (var i = 0; i < 20; i++)
        {
            var row = {
                f1:"f1x" + i, 
                f2:"f2x" + i, 
                f3:"f3x"+i, 
                f4:"f4x"+i,
                f5:"f5x"+i,
                f6:"f6x"+i,
                f7:"f7x"+i,
                f8:"f8x"+i,
                f9:"f9x"+i,
                f10:"f10x"+i,
                f11:"f11x"+i,
                f12:"f12x"+i,
                f13:"f13x"+i
                };
            mydata.push(row);
        }

        // push it to angulars scope
        $scope.mydata = mydata;

        // generate some metadata for the columns
        $scope.mycolumns = [{
            name: "Column 1",
            fieldname: "f1",
            type: "input"
        }, {
            name: "Column 2",
            fieldname: "f2",
            type: "textarea"
        }, {
            name: "Column 3",
            fieldname: "f3",
            type: "div"
        }, {
            name: "Column 4",
            fieldname: "f4",
            type: "div"
        }, {
            name: "Column 5",
            fieldname: "f5",
            type: "div"
        }, {
            name: "Column 6",
            fieldname: "f6",
            type: "div"
        }, {
            name: "Column 7",
            fieldname: "f7",
            type: "div"
        }, {
            name: "Column 8",
            fieldname: "f8",
            type: "div"
        }, {
            name: "Column 9",
            fieldname: "f9",
            type: "div"
        }, {
            name: "Column 10",
            fieldname: "f10",
            type: "div"
        }, {
            name: "Column 11",
            fieldname: "f11",
            type: "div"
        }, {
            name: "Column 12",
            fieldname: "f12",
            type: "div"
        }, {
            name: "Column 13",
            fieldname: "f13",
            type: "div"
        }];

        $scope.showdata = function () {
            alert(JSON.stringify($scope.mydata));
        };

        $scope.getcolumnname = function (cell) {
            return cell.fieldname;
        };
    }

    function changediv()
    {
        // this will change the data in the divs but it won't reflect back to the scope

        var divs = document.getElementsByClassName("fred");
        for (var i = 0; i < divs.length; i++)
        {
            var div = divs[i];
            div.innerText = "XXXX";
        }

    }

    function changescope()
    {
        // shows how to change data programmatically and have it reflected in the controls and in the scope data

        var scope = globalscope;
        for (r in scope.mydata)
        {
            scope.mydata[r].f3 = "UUUU";
        }
        scope.$apply();
    }
</script>
Sign up to request clarification or add additional context in comments.

2 Comments

That's awesome but do you a way to do the same in Angular 2? <mycontrol data-my-model="record[cell.fieldname]"></mycontrol> . Followed up question is here stackoverflow.com/questions/38810318/…
Sorry, ended up not using angular at all, and indeed noone else's libraries whatsoever (except JQ) - much better !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.