0

I'm running an angular / mvc website. And I separate all my model and stuff. At some point I feel need of an extra property which is not part of my model. I though of inheritance and start writing codes. first I went with 'getter', seeing it's get override simply, I though about something more supported by intellisense like method, so one won't simply override it without thinking.

here what I write:

/**
 * Created by Hassan on 4/4/2016.
 */
abstract class DynamicPropertiesProvider {
    private _dynamicProperties:Object;

    constructor() {
        this._dynamicProperties = {};
    }

    dynamicProperties():Object {
        return this._dynamicProperties;
    }
}

and then i use it in my model like:

/**
 * Created by Hassan on 3/16/2016.
 */

///<reference path="dynamicPropertiesProvider.ts"/>
class AcDocRow extends DynamicPropertiesProvider{
    public FinYear: string;
    public DocNoTemp: number;
    public DocRow: number;
    public HsbCod: string;
    public RowDsc: string;
    public Bedehkar: number;
    public Bestankar: number;
    public Bookmark: boolean;
    public MainDocNo: number;
    public DocDate: string;

    //Getters And Setters
    get CompositeKey():string {
        return this.FinYear + "-" + this.DocNoTemp + "-" + this.DocRow;
    }

    get Date():string {
        return ((this.DocDate) ? this.DocDate.substr(0, 4) + "/" + this.DocDate.substr(4, 2) + "/" + this.DocDate.substr(6, 2) : "");
    }

    constructor(finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate){
        super(); //Call Super (Parent) Class Constructor
        this.setup();
        if (finYear != undefined) this.FinYear = finYear;
        if (docNoTemp != undefined) this.DocNoTemp = docNoTemp;
        if (docRow != undefined) this.DocRow = docRow;
        if (hsbCod != undefined) this.HsbCod = hsbCod;
        if (rowDsc != undefined) this.RowDsc= rowDsc;
        if (bedehkar != undefined) this.Bedehkar = bedehkar;
        if (bestankar != undefined) this.Bestankar= bestankar;
        if (bookmark != undefined) this.Bookmark = bookmark;
        if (mainDocNo != undefined) this.MainDocNo= mainDocNo;
        if (docDate != undefined) this.DocDate= docDate;
    }

    private setup():void{
        this.FinYear = "";
        this.DocNoTemp = 0;
        this.DocRow = 0;
        this.HsbCod = "";
        this.RowDsc = "";
        this.Bedehkar = 0;
        this.Bestankar = 0;
        this.Bookmark = false;
        this.MainDocNo = 0;
        this.DocDate = "";
    }

    public copy():AcDocRow{
        return new AcDocRow(this.FinYear, this.DocNoTemp, this.DocRow, this.HsbCod, this.RowDsc, this.Bedehkar, this.Bestankar, this.Bookmark, this.MainDocNo, this.DocDate);
    }

    public resetModel(finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate): void{
        this.constructor(finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate);
    }
}

but the compiled JS, does not contains the method i wrote in 'DynamicPropertiesProvider' class:

For DynamicPropertiesProvider:

/**
 * Created by Hassan on 4/4/2016.
 */
var DynamicPropertiesProvider = (function () {
    function DynamicPropertiesProvider() {
        this._dynamicProperties = {};
    }
    DynamicPropertiesProvider.prototype.dynamicProperties = function () {
        return this._dynamicProperties;
    };
    return DynamicPropertiesProvider;
})();
//# sourceMappingURL=dynamicPropertiesProvider.js.map

For AcDocRow:

/**
 * Created by Hassan on 3/16/2016.
 */
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
///<reference path="dynamicPropertiesProvider.ts"/>
var AcDocRow = (function (_super) {
    __extends(AcDocRow, _super);
    function AcDocRow(finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate) {
        _super.call(this); //Call Super (Parent) Class Constructor
        this.setup();
        if (finYear != undefined)
            this.FinYear = finYear;
        if (docNoTemp != undefined)
            this.DocNoTemp = docNoTemp;
        if (docRow != undefined)
            this.DocRow = docRow;
        if (hsbCod != undefined)
            this.HsbCod = hsbCod;
        if (rowDsc != undefined)
            this.RowDsc = rowDsc;
        if (bedehkar != undefined)
            this.Bedehkar = bedehkar;
        if (bestankar != undefined)
            this.Bestankar = bestankar;
        if (bookmark != undefined)
            this.Bookmark = bookmark;
        if (mainDocNo != undefined)
            this.MainDocNo = mainDocNo;
        if (docDate != undefined)
            this.DocDate = docDate;
    }
    Object.defineProperty(AcDocRow.prototype, "CompositeKey", {
        //Getters And Setters
        get: function () {
            return this.FinYear + "-" + this.DocNoTemp + "-" + this.DocRow;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AcDocRow.prototype, "Date", {
        get: function () {
            return ((this.DocDate) ? this.DocDate.substr(0, 4) + "/" + this.DocDate.substr(4, 2) + "/" + this.DocDate.substr(6, 2) : "");
        },
        enumerable: true,
        configurable: true
    });
    AcDocRow.prototype.setup = function () {
        this.FinYear = "";
        this.DocNoTemp = 0;
        this.DocRow = 0;
        this.HsbCod = "";
        this.RowDsc = "";
        this.Bedehkar = 0;
        this.Bestankar = 0;
        this.Bookmark = false;
        this.MainDocNo = 0;
        this.DocDate = "";
    };
    AcDocRow.prototype.copy = function () {
        return new AcDocRow(this.FinYear, this.DocNoTemp, this.DocRow, this.HsbCod, this.RowDsc, this.Bedehkar, this.Bestankar, this.Bookmark, this.MainDocNo, this.DocDate);
    };
    AcDocRow.prototype.resetModel = function (finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate) {
        this.constructor(finYear, docNoTemp, docRow, hsbCod, rowDsc, bedehkar, bestankar, bookmark, mainDocNo, docDate);
    };
    return AcDocRow;
})(DynamicPropertiesProvider);
//# sourceMappingURL=acDocRow.js.map

My ts compiler is the one come along with WebStrom 11.0 and i aslo set '--target es5' flag.

what should i do?

enter image description here

enter image description here


Edit due iberbeu comment:

My Service Where i read the data from server, and then i create a AcDocRow object from them

app.factory("AcDocRowService",
    ["$resource",
        function ($resource) {
            //noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
            return $resource("/api/AcDocRows/:id:filter:param1/:param2",
                {
                    id: "@id",
                    param1: "@param1",
                    param2: "@param2",
                    filter: "@filter"
                },
                {
                    "query": {
                        method: "GET",
                        isArray: true,
                        transformResponse: function(data, header) {
                            var wrapped = angular.fromJson(data);
                            //If contains exceptions, it is not a list and should return directly without modification
                            //noinspection JSUnresolvedVariable
                            if (!wrapped.ExceptionType && !wrapped.ExceptionMessage) {
                                angular.forEach(wrapped, function (item, idx) {
                                    wrapped[idx] = new AcDocRow(
                                        wrapped[idx].FinYear,
                                        wrapped[idx].DocNoTemp,
                                        wrapped[idx].DocRow,
                                        wrapped[idx].HsbCod,
                                        wrapped[idx].RowDsc,
                                        wrapped[idx].Bedehkar,
                                        wrapped[idx].Bestankar,
                                        wrapped[idx].Bookmark,
                                        wrapped[idx].MainDocNo,
                                        wrapped[idx].DocDate
                                    );
                                });
                            }
                            return wrapped;
                        }
                    },
                    "get": {
                        method: "GET",
                        isArray: false
                    },
                    "update": {
                        method: "PUT"
                    },
                    "setBookmark":{
                        method: "PUT",
                        params:{
                            param2: "SetBookmark"
                        }
                    }
                }
            );
        }
    ]
);

My controller when i tell service to return data, and then i bind it to the view.

app.controller("IndexController", [
    "$rootScope", "$scope", "$uibModal", "$timeout", "AcDocRowService", "FinYearService",
    function ($rootScope, $scope, $uibModal, $timeout, AcDocRowService, FinYearService) {

        $scope.View = {
            SarfaslSelectionDialog: {
                ShowDialog: false,
                /**
                 * Output Result Selected Sarfasl
                 */
                SelectedSarfasl: null,
                FinYear: null,
                InitialHsbCod: null
            },
            CodeInfo: {
                LenCod: 0,
                LenK: 0,
                LenM: 0,
                LenT1: 0,
                LenT2: 0,
                LenJ: 0
            },
            OperationMode: null,
            Errors: [],
            AcDocRowList: [],
            AcDocRowFilters:{
                ShowFilters: false,
                Bookmark: null,
                FromDate: "",
                ToDate: "",
                FromDocNoTemp: null,
                ToDocNoTemp: null,
                FromPrice: null,
                ToPrice: null
            },
            AcDocRowSummery: {
                TotalResult: 0,
                CheckedResult: 0,
                UncheckedResult: 0,
                TotalDemand: 0,
                TotalDept: 0,
                CheckedDemand: 0,
                CheckedDept: 0,
                UncheckedDemand: 0,
                UncheckedDept: 0
            },
            SelectedItems: []
        };

        $scope.Events= {
            selectRow: function(row){
                if($scope.View.SelectedItems.contains(row)){
                    $scope.View.SelectedItems.remove(row);
                } else {
                    $scope.View.SelectedItems.push(row)
                }

                //MY OLD CODES WHERE I READ THE 'row' Object

                //if(! row.dynamicProperties()["selected"])
                //    row.dynamicProperties()["selected"]= true;
                //row.dynamicProperties()["selected"] = !row.dynamicProperties()["selected"];
            },
            ...
            //Where i set AcDocRowList, That i use in my View
            searchAcDocRows: function() {
                $scope.Events.openWaitDialog();

                //If Method Called On Start By $Watch, Return
                if($scope.View.SarfaslSelectionDialog.SelectedSarfasl == null){
                    return;
                }

                var sarfaslParams = $scope.View.SarfaslSelectionDialog;

                var filter = "FinYear=" + sarfaslParams.FinYear + "-HsbCod=" + sarfaslParams.SelectedSarfasl.getClearHsbCod();
                AcDocRowService.query({ filter: filter }).$promise.then(
                    function (data) {
                        $scope.Methods.resetTotals();
                        $scope.View.AcDocRowList = data;
                        $scope.Events.closeWaitDialog();
                    }, function (errorResult) {
                        $scope.View.Errors.push(new Alert("Cannot contact web server at this moment. Please try again later.", AlertType.Danger));
                        $scope.Events.closeWaitDialog();
                    }
                );
            }
            ...
        };
        ...

    }
]);

My View:

...
            <tbody>
                <tr data-ng-repeat="row in View.AcDocRowList | filter: Filters.acDocRowFilterFunction"
                    data-ng-class="{'checked-row':row.Bookmark}" data-ng-click="Events.selectRow(row)">
                    <td>
                        <input type="checkbox" ng-model="row.Bookmark" data-ng-click="Events.setBookmark(row)">
                    </td>
                    <td class="number">
                        <!--Restart Total Price-->
                        {{Methods.setTotal($index, row.Bookmark); $index | persianNumberFilter}}
                    </td>
                    <td class="number">{{row.DocNoTemp | persianNumberFilter}}</td>
                    <td>
                        <!--row.Date is a 'getter' -->
                        {{row.Date | persianNumberFilter}}
                    </td>
                    <td>{{row.RowDsc | persianNumberFilter}}</td>
                    <td class="number">{{row.Bedehkar!=0?row.Bedehkar:"" | priceFilter | persianNumberFilter}}</td>
                    <td class="number">{{row.Bestankar!=0?row.Bestankar:"" | priceFilter | persianNumberFilter}}</td>
                    <td>
                        {{Methods.getTashkhis()}}
                    </td>
                    <td class="number">
                        {{Methods.getRemains()!=0?Methods.getRemains():"" | priceFilter | persianNumberFilter}}
                    </td>
                </tr>
            </tbody>
...

Solved

AngularJs ngResource doesn't parse transformResponse action directly. it pass it to $http in angular core to handle it. and once the result come out. it again fold the data inside object of Resource class. that's when resource constructor do a shallow copy as it named the method. and as it's name says lot of things in the deeper level go loss, also object type get changed.

I fix the issue with updating the angular ngResource and provide with new action "transformResult", and I use it instead of transformResponse. it perform it's job at the end before ngResource pass results to the user.

https://github.com/deadmann/code.angularjs.org/blob/master/1.4.9/angular-resource.js

I also made pull request, which I don't think so, but I hope they accept. https://github.com/angular/code.angularjs.org/pull/35

6
  • abstract classes are only available after typescript version 1.6 Are you compiling with 1.6 or greater? Commented Apr 4, 2016 at 14:45
  • compiler version: 1.6.2 (bundled) Commented Apr 5, 2016 at 5:03
  • The compilation is fine. If your paste your code here typescriptlang.org/play you will get the same compilation and it works. I guess your problem is that ´row´ is not the object type you are waiting for Commented Apr 5, 2016 at 7:05
  • i modified my post, and add my angular binding information Commented Apr 5, 2016 at 7:34
  • the cod in controller and service is not typescript. so how are you sure that you pass the right types? There are 2 options: row is not of wanted type or as basarat said the files are not getting compiled in the right order Commented Apr 5, 2016 at 9:12

2 Answers 2

0

I suspect you have a module ordering problem. I recommend not using outFile and looking into using a module pattern e.g. commonjs : https://github.com/TypeStrong/atom-typescript/blob/master/docs/out.md

Sign up to request clarification or add additional context in comments.

3 Comments

so you mean my AcDocRow need recompiling? i gave it a try, and it didn't worked. or you mean something else
I mean the order if compiled JavaScript might be wrong. E.g. something like console.log(foo); var foo =123 instead of var foo =123;console.log(foo); might be happening.
i tried that (first i compiled the abstract, and then the inherited class)... not working... and inside the js file... it gave error before, so i put the parent file in the beginning of bundling queue
0

I modified the ngResource, and made a pull request, which provide transforming latest result from a service. https://github.com/angular/angular.js/pull/14381

Comments

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.