2

This may look like a silly question, but it almost take an entire 3 hours, but still couldn't figure out what I have done wrong here. Possibly some one can point out the reason and how to fix this issue (I feel this is a easy fix, but still couldn't see it). So here's the matter, I have this javascript library integrated to angularJS application. I used a angular factory to provide this service to where it needs, so I can bind this to a single button click event, and initiate the functionalities of the integrated library. Now I need to take some values as parameters from the controller this factory function uses and pass those values from the factory to controller which is the controller that responsible for initiate the third party library. here's what I have so far.

This is a git repository with the same error

enter image description here

imageEditor factory

(function() {
    'use strict';

    angular.module('appEdit').factory('imageEditorService', [
        '$mdDialog',imageEditorService
    ]);

    function imageEditorService($mdDialog) {
        return {

            showImageEditorDialog: function (_width,_height) {

                return $mdDialog.show({
                    controller: 'imageEditorCtrl',
                    templateUrl: './imageEditor.html',
                    clickOutsideToClose: true,
                    locals: {
                        initialData: null,
                        width: _width,
                        height: _height
                    }
                });
            },
        };
    }
})();

imageEditor Controller

(function() {
    'use strict';
    angular.module("appEdit").controller("imageEditorCtrl" , ['width','height',imageEditorCtrl]);


    function imageEditorCtrl(width,height) {
        //this outputs the width, height passed to this properly
        console.log(width+','+height);

        setTimeout(
            () => {

                var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
                    includeUI: {
                        loadImage: {
                            path: './images/imageEditor/test.png',
                            name: 'SampleImage'
                        },
                        theme: blackTheme,
                        initMenu: 'crop',
                        menuBarPosition: 'bottom'
                    },
                    cssMaxWidth: 700,
                    cssMaxHeight: 300
                });

                // this is where I need the width, height should be bound
                imageEditor.setCropRect(width,height);

                window.onresize = function () {
                    imageEditor.ui.resizeEditor();
                }

            }
            , 1000)
    };

})();

mainController

(function(){
"use strict";

angular.module('appEdit')
    .controller('mainCtrl', ['$scope','imageEditorService', function ($scope, imageEditorService) {

        $scope.openImageEditorDialog = function (width, height) {
            imageEditorService.showImageEditorDialog(width, height);
    };
    }]);
 })();

HTML where I used this mainCtrl

<div ng-controller="mainCtrl">
    <md-button ng-click="openImageEditorDialog(400,200)">Open</md-button>
</div>

The Error

angular.js:14110 Error: [$injector:unpr] Unknown provider: widthProvider <- width <- imageEditorCtrl http://errors.angularjs.org/1.5.9/$injector/unpr?p0=widthProvider%20%3C-%20width%20%3C-%20imageEditorCtrl at http://localhost:1337/vendor/angular/angular.js:68:12 at http://localhost:1337/vendor/angular/angular.js:4554:19 at Object.getService [as get] (http://localhost:1337/vendor/angular/angular.js:4707:32) at http://localhost:1337/vendor/angular/angular.js:4559:45 at getService (http://localhost:1337/vendor/angular/angular.js:4707:32) at injectionArgs (http://localhost:1337/vendor/angular/angular.js:4732:58) at Object.invoke (http://localhost:1337/vendor/angular/angular.js:4754:18) at $controllerInit (http://localhost:1337/vendor/angular/angular.js:10518:34) at nodeLinkFn (http://localhost:1337/vendor/angular/angular.js:9416:34) at compositeLinkFn (http://localhost:1337/vendor/angular/angular.js:8757:13) undefined

I know this error occurs with a typo kind of issues, but here I can not understand why this occurs. with console.log(width+','+height) I could confirm the width and height is set properly and it comes to the controller, but the problem is with the provided error, entire functionality of the third party library is breaks down(it won't initiate at all). without the width, height parameters it works just fine

Sanira Nimantha
  • 1,160
  • 1
  • 12
  • 29
  • Where should these values come from? From the URL? From inputs in the view? – Renato Lucas Chitolina Oct 08 '18 at 11:49
  • @RenatoLucasChitolina I just updated the question, for better understand. Hop you can understand the problem than before now. – Sanira Nimantha Oct 08 '18 at 11:53
  • Which version of angularJS you are using? – Gangadhar Jannu Oct 08 '18 at 12:09
  • Where are you getting width and height for this line `imageEditor.setCropRect(width,height);` – Gangadhar Jannu Oct 08 '18 at 12:10
  • @GangadharJannu it's angular v-1.7.5 and `function imageEditorCtrl(width,height)` this is where it comes. – Sanira Nimantha Oct 08 '18 at 12:15
  • Now this makes sense. Remove width, height params for your controller – Gangadhar Jannu Oct 08 '18 at 12:26
  • @GangadharJannu I know it will solve the problem, But what if I need to pass those values from the `factory` to `controller` ? – Sanira Nimantha Oct 08 '18 at 12:30
  • @Sanira Can you check my [answer](https://stackoverflow.com/a/52702649/3543808) let me know if it works? – Gangadhar Jannu Oct 08 '18 at 12:46
  • You're using v1.7.5? Then why url in error points to v1.5.9? I can't see `angular` (without suffix) in your `package.json` nor in `bower.json`. Are you sure that both pure angularjs and addons are v1.7.5? – barbsan Oct 10 '18 at 07:54
  • @barbsan It's a big project from my company and a pretty old one. So there can be some conflicts, but I personally implement this code with angular v1.7.4. It has nothing but the files regarding to this matter. so it gives me the same error. I'll update the question with that error message. – Sanira Nimantha Oct 10 '18 at 09:05
  • @barbsan It's a big project from my company and a pretty old one. So there can be some conflicts, but I personally implement this code with angular v1.7.4. It has nothing but the files regarding to this matter. so it gives me the same error. I'll put that error here – Sanira Nimantha Oct 10 '18 at 09:14
  • Error: [$injector:unpr] Unknown provider: widthProvider <- width <- editorUICtrl https://errors.angularjs.org/1.7.4/$injector/unpr?p0=widthProvider%20%3C-%20width%20%3C-%20editorUICtrl at angular.js:138 at angular.js:4905 at Object.getService [as get] (angular.js:5065) at angular.js:4910 at getService (angular.js:5065) at injectionArgs (angular.js:5090) at Object.invoke (angular.js:5114) at $controllerInit (angular.js:11673) at nodeLinkFn (angular.js:10486) at compositeLinkFn (angular.js:9801) – Sanira Nimantha Oct 10 '18 at 09:15

3 Answers3

1

Seems like the issue is with Dependency Injection.

Change your imageEditor Controller definition as below

(function () {
    'use strict';
    angular.module("appEdit").controller("imageEditorCtrl", [imageEditorCtrl]);

    function imageEditorCtrl($scope, $mdDialog, initialData, width, height) {
        this.$onInit = function () {
            var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
                includeUI: {
                    loadImage: {
                        path: './images/imageEditor/test.png',
                        name: 'SampleImage'
                    },
                    theme: blackTheme,
                    initMenu: 'crop',
                    menuBarPosition: 'bottom'
                },
                cssMaxWidth: 700,
                cssMaxHeight: 300
            });

            // this is where I need the width, height should be bound
            imageEditor.setCropRect(width, height);

            window.onresize = function () {
                imageEditor.ui.resizeEditor();
            }
        }
    };
})();
Gangadhar Jannu
  • 4,136
  • 6
  • 29
  • 49
  • Already try those bro, still no luck. no errors with `$scope` or `$mdDialog`, it's just the `width` and `height` gives the error. I'll try to add a `plunker` or `fiddle` regarding this. – Sanira Nimantha Oct 08 '18 at 12:51
  • That would really help us in debug the issue – Gangadhar Jannu Oct 08 '18 at 12:53
  • I have linked a git repo with the same error, You can refer to that. – Sanira Nimantha Oct 08 '18 at 13:17
  • still not working?. Have you tried my updated answer? – Gangadhar Jannu Oct 08 '18 at 13:24
  • I tried the updated one mate, still no luck. width and height undefined then. I suspect it happens with `setTimeout` – Sanira Nimantha Oct 09 '18 at 04:42
  • Would be great if you could provide a fiddle or jsbin so that we can debug. We can see the code from GitHub but we can't debug that – Gangadhar Jannu Oct 09 '18 at 04:44
  • mate I tried everything, but couldn't reproduce the error or make it work with any of the online code editor. If you could clone my repository and run it with a server(apache, etc) you'll be able to see the error with my code. I am working with a big project, So the solution for this issue is the key for everything. Still no luck with any changes I've being trying. – Sanira Nimantha Oct 09 '18 at 11:45
  • The error clearly shows that `width` is an unknown provider. I'm still confused why the below code is not working `angular.module("appEdit").controller("imageEditorCtrl" , [imageEditorCtrl])` – Gangadhar Jannu Oct 09 '18 at 11:53
  • You have to remote `width` and `height` in array. Have you done that? – Gangadhar Jannu Oct 09 '18 at 11:53
  • "You have to remote `width` and `height` in array." what do you mean by that? – Sanira Nimantha Oct 09 '18 at 12:38
  • Just replace your imageEditorCtrl definition with the one I have suggested in my comment – Gangadhar Jannu Oct 09 '18 at 12:40
  • Ya, then `TypeError: Cannot read property 'classList' of null` error occurs, to overcome that I have to put the code snippet inside the `setTimeout()` then the same error occurs. **And with this one `width` and `height` become undefined** – Sanira Nimantha Oct 09 '18 at 12:47
0

There are several problems with your code, but the main thing you need to get down is Dependency Injection(DI) in angularJS:

https://docs.angularjs.org/guide/di

You created your service, imageEditorService, but you need to inject it in your controller:

angular.module("appEdit").controller("imageEditorCtrl" , ['imageEditorService',imageEditorCtrl]);


function imageEditorCtrl(imageEditorService) {

You cannot inject 'height' and 'width' into your controller, as they are not 'providers', as your error suggests. To use the service in your controller, call:

imageEditorService.showImageEditorDialog(height, width); // Specify the height and width. 

That said, I am not sure what you want to do in your controller. Do you want to instantiate a new tui.ImageEditor, or do you want to use your imageEditorService?

If you want to use tui.ImageEditor, use your factory/service to do that.

Some tips: Make sure you understand the difference between controllers and services/factories/providers. Also, get familiar with the controller lifecycle, such as the build-in init hook:

What is the lifecycle of an AngularJS Controller?.

  • Seems like you didn't understand the question properly. I used this factory to just initiate the image editor. so it makes it ease to inject into any controller and using it I can instantiate the image editor where ever I need. BTW I know the difference between a controller/service/factory and a provider. This way I can pass the values to the controller, **which is the controller bound to the factory, but when I use this method to pass the values, the image editor instantiation disrupted some how**. How ever I can see the question doesn't seems clear, I'll update the question. – Sanira Nimantha Oct 08 '18 at 11:41
0

Finally I sort it out, I did a really really stupid thing, and as I was suspecting It was just an easy fix. I just bind the controller again to the templateHTML, and that causes the problem. it's just confuse the build flow with the same controller which binds to a HTML Element twice. So just removing the controller bind from the templateHTML file, just fix the problem.

previous templateURL file

<div ng-controller="imageEditorCtrl"> <!--this line which causes the problem with controller bind-->
    <div style="width:80vw; height: 500px">
        <div id="tui-image-editor-container"></div>
    </div>
</div>

fixed version

<div>
    <div style="width:80vw; height: 500px">
        <div id="tui-image-editor-container"></div>
    </div>
</div>
Sanira Nimantha
  • 1,160
  • 1
  • 12
  • 29