0

I'm very much trying to get my head around angularJS and directives still.

I have an existing REST service that outputs JSON data as follows (formatted for readability):

{"ApplicationType":
    ["Max","Maya","AfterEffects","Nuke","WebClient","Other"],
"FeatureCategory":
    ["General","Animation","Compositing","Management","Other"],
"FeatureStatus":
    ["Completed","WIP","NotStarted","Cancelled","Rejected","PendingReview"],
"BugStatus":
    ["Solved","FixInProgress","NotStarted","Dismissed","PendingReview"]}

I then have a service (which appears to be working correctly) to retrieve that data that I wish to inject into my directive.

(function () {
'use strict';

var enumService = angular.module('enumService', ['ngResource']);

enumService.factory('Enums', ['$resource',
function ($resource) {
    return $resource('/api/Enums', {}, {
        query: { method: 'GET', cache: false, params: {}, isArray: false }
    });
}
]); })();

My intentions are to use the data from the json response to bind to html selector 'options' for the purposes of keeping the data consistent between the code behind REST service and the angular ( ie. the json data is describing strongly typed model data from c# eg. Enum.GetNames(typeof(ApplicationType)) )

projMgrApp.directive('enumOptions', ['Enums',
function (Enums) {
    return {
        restrict: 'EA',
        template: '<option ng-repeat="op in options">{{op}}</option>',
        scope: {
            key: '@'
        },
        controller: function($scope) { },
        link: function (scope, element, attrs) {
            scope.options = Enums.query(function (result) { scope.options = result[scope.key]; });
        }
    };

}
]);

the intended usage would be to use as follows:

<label for="Application" class="control-label col-med-3 col">Application:</label>
                <select id="Application" class="form-control col-med-3 col pull-right">
                    <enum-options key="ApplicationType"></enum-options>
                </select>

which would then produce all of the options consistent with my c# enums.

In this case it appears the directive is never being called when the tag is used.

Note. I assume the factory is working fine, as i can inject it into a separate controller and it works as anticipated.

8
  • what is your error message ? Commented Feb 17, 2016 at 8:13
  • Failed to instantiate module projMgrApp due to: Error: [$compile:baddir] errors.angularjs.org/1.5.0/$compile/baddir?p0=Enum... at Error (native) at localhost:3240/lib/angular/angular.min.js:6:416 Commented Feb 17, 2016 at 8:16
  • docs.angularjs.org/error/$compile/baddir Directives must start with a lowercase character and must not contain leading or trailing whitespaces. Commented Feb 17, 2016 at 8:18
  • that does stop the error from being generated (thanks!), though it doesnt return the options.. that is neither the array that was intialized when scope was declared, or the array returned from the REST Commented Feb 17, 2016 at 8:22
  • can you edit this function and past what is logged ? scope.options = Enums.query(function (result) { console.log(JSON.stringify(result, undefined, 2)); scope.options = result[scope.key]; }); Commented Feb 17, 2016 at 8:29

3 Answers 3

1

1) I guess projMgrApp is the main module. Have you included enumService as dependency to this module?

angular.module('projMgrApp',['enumServices'])

Otherwise your main module won't be aware of the existence of your service.

2) Are you aware how the directives are declared and used. When you declare

projMgrApp.directive('EnumOptions', ['Enums', function (Enums) {}])

actually should be used in the html code as:

<enum-options></enum-options>

I m not quite sure about the name but it should start with lowercase letter like enumOptions

3) I don't know why you use this key as attribute. You don't process it at all. scope.key won't work. You either have to parse the attributes in link function (link: function(scope, element, attributes)) or create isolated scope for the directive.

Add as property of the return object the following:

scope : {
  key:'@' //here depends if you want to take it as a string or you will set a scope variable.
}

After you have this , you can use it in the link function as you did (scope.key).

Edit:

Here is a working version similar (optimized no to use http calls) to what you want to achieve. Tell me if I'm missing anything. Working example

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

5 Comments

ok, 1 and 2 i was aware of ( though admittedly i had missed the <enum-options> tag capitalization ( a symptom of being 2 days into angular and absorbing a tonne of info v. quickly I presume ).
I have adjusted the points you made in 3), however, im still obviously missing something as its getting no return.
Ive updated the code in the main post to reflect the changes.
Can you somehow show the whole project. Also it will be really nice to display all the errors you receive!
Also I suggest to use $http.
0

If you get the baddir error try to rename your directive name to enumOptions according to the doc (don't forget the injection):

 This error occurs when the name of a directive is not valid.

 Directives must start with a lowercase character and must not contain leading or trailing whitespaces.

1 Comment

thanks. that does help as it stops the error from being generated.. However, its not returning the options ( with no error being generated ). That is neither the array that was intialized when scope was declared, or the array returned from the REST
0

Thanks to Tek's suggestions I was able to get this fully functioning as intended. Which means now my angularJS + HTML select tags/directives are completely bound to my APIs enums. I know down the line that I am going to be needing to adjust add to these occasionally based on user feedback, plus I use these enums to represent strongly typed data all over the app. So it will be a big time saver and help reduce code repetition. Thanks to everyone that helped!

The service and directive that I used is copied below, in case other people starting out with Angular run into similar issues or have similar requirements.

Service:

(function () {
'use strict';

var enumService = angular.module('enumService', [])

.service('Enums', ['$http', '$q', function ($http, $q) {
    return {
        fetch: function () {
            var defer = $q.defer();
            var promise = $http.get("/api/Enums").then(function (result) {
                defer.resolve(result);
            });
            return defer.promise;
        }
     }
 }]);})();

Directive:

angular.module('projMgrApp').directive('enumOptions', ['Enums', function (Enums) {
    return {
        restrict: "EA",
        scope: {
            key: "@"
        },
        template: "<select><option ng-repeat='enum in enumIds' ng-bind='enum'></option><select>",
        link: function (scope) {
            Enums.fetch().then(function (result) {
                scope.enumIds = result.data[scope.key];
            });
        }
    };
}]);

3 Comments

I see you point with the select but I think it will be better to include the select into the directive itself.
What errors do you see and what do you want to achieve?
No errors. The directive isn't called from an options tag. Ive put it on a select and now it is calling so i intend to build the template with a stringbuilder or whatever the equivalent is in javascript.

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.