0

UPDATE: Apparently setting the controller in the view such ng-controller="SomethingController as Ctrl" and then using it in the model ng-model="Ctrl.myModel" works. What the f***?

I've been meaning to implement this specific directive on my application. It simply requires me to put my model as an attribute of the element as ng-model="myModel" and it should work. I see examples of it working, and I've made it work on jsfiddle too.

However it simple does not want to work on my app. I have installed through bower, I've included all the files in my index.html and I've also injected it angular.module('myApp', ['angular-input-stars']).

Now the issues is, the model only works one way through on my application. The ng-model="myModel" uses myModel's value and sets the correct amount of stars, but once I change the stars (in and through the directive) that value is not being sent back to my model.

I've checked the directive's code and they do use the model controller set the value:

function link(scope, element, attrs, ngModelCtrl) {
    //...

    scope.setValue = function (index, e) {
         //...
        ngModelCtrl.$setViewValue(scope.last_value);
    }    
}

And even though the directive does not include in the return that scope: {ngModel: '='}, this still works on examples and jsFiddle, even though I don't really understand the $setViewValue (even after researching about it).

I think it may have something to do with my application's architecture, but I'm not sure. The app is very robust and well structured, and I cannot display it's code (company code), but I can say how we structured it:

|-- app.js (contains directive module, show bellow)
|-- index.html
|-- /modules
      |-- /something
            |-- /overview
                  |-- somethingController.js 
                      (included in index.html & loaded through directive)
                  |-- somethingDirective.js
                      (included in index.html & loaded through app.js module)
                  |-- somethingView.html
                      (loaded through directive)

app.js code:

var app = angular.module('myApp', [
    'angular-input-stars',
    'something.overview'
]);

somethingDirective.js:

var somethingOverview = angular.module('something.overview');

somethingOverview.directive('somethingOverviewDirective', function () {
    return {
        restrict: 'E',
        controller: 'SomethingOverviewController',
        templateUrl:     'modules/something/overview/somethingOverviewView.html',
        scope: {
            overview: '=overview',
            errors: '=errors'
        }
    };
});

somethingController.js:

var somethingOverview = angular.module('something.overview', []);

somethingOverview.controller('SomethingOverviewController', 
    ['$scope', function ($scope) {
        function init() {
            $scope.myModel = 5;
        }

        // ...

        init();
    }]);

somethingView.html:

<div>
    Rating: {{myModel}}
    <input-stars max="5" ng-model="myModel"></input-stars>
</div>
Ted
  • 580
  • 4
  • 22
  • Can you paste the link to the jsfiddle here? – Jesper Jun 03 '16 at 11:31
  • The biggest and only difference I see is that in the jsfiddle i use "myCtrl as Ctrl" and then use the "Ctrl" to access the model. Could this be it? And if so, how can I do that "as" when the view is loaded by directive? Here: https://jsfiddle.net/filipetedim/14f05jdb/1/ – Ted Jun 03 '16 at 11:37
  • 2
    You are breaking the golden rule of always having a dot in ng-model. Primitives do not have inheritance. Watch 3 minute video in answer to http://stackoverflow.com/questions/17606936/angularjs-dot-in-ng-model – charlietfl Jun 03 '16 at 11:51
  • @charlietfl but how will that fix my problem? Because I don't want to set my controller AS something in the view, since it's set through the directive. – Ted Jun 03 '16 at 11:55
  • 1
    `$scope.myModel` needs to be object and also you have isolated scope in directive so need to pass it into directive also – charlietfl Jun 03 '16 at 11:59
  • I see now. Thanks for the answer @charlietfl ! – Ted Jun 03 '16 at 12:23

1 Answers1

2

As @charlietfl mentioned in the comments, primitive value in scope directly is the problem

Code without controllerAs:

<div ng-app="myApp">
    <h3>Greetings</h3>
    <div ng-controller="MyCtrl">
        Hello, {{name}}!

        <div>Rating: {{rating}}</div>

        <input-stars ng-model="rating.value" max="5"></input-stars> 
    </div>
</div>


app.controller("MyCtrl", ['$scope', function($scope) {
    $scope.rating = {
        value: 5
    };
    $scope.name = 'Superhero';

}]);

Updated jsFiddle:

https://jsfiddle.net/14f05jdb/3/

Muthukannan Kanniappan
  • 2,080
  • 1
  • 16
  • 18
  • This is the correct answer. I'd like to give props to @charlietfl who explained to me before this. – Ted Jun 03 '16 at 12:25