jadjoubran / laravel5-angular-material-starter

Get started with Laravel 5.3 and AngularJS (material)
https://laravel-angular.readme.io/
MIT License
1.66k stars 400 forks source link

Error with satellizer on Chrome, working great on Safari #214

Closed iannazzi closed 8 years ago

iannazzi commented 8 years ago

@jadjoubran I am integrating the new satellizer commit, thanks for that. Seems to work as expected in safari. In Chrome I receive the following error when submitting login info....but I can't figure it out. Might be from the loading bar? I know if I remove satellizer I can get rid of the error.

angular.js:13294 Error: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'Bearer <script> Sfdump = window.Sfdump || (function (doc) { var refStyle = doc.createElement('style'), rxEsc = /([.*+?^${}()|\[\]\/\\])/g, idRx = /\bsf-dump-\d+-ref[012]\w+\b/, keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', addEventListener = function (e, n, cb) { e.addEventListener(n, cb, false); }; (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); if (!doc.addEventListener) { addEventListener = function (element, eventName, callback) { element.attachEvent('on' + eventName, function (e) { e.preventDefault = function () {e.returnValue = false;}; e.target = e.srcElement; callback(e); }); }; } function toggle(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; if ('sf-dump-compact' == oldClass) { arrow = '&#9660;'; newClass = 'sf-dump-expanded'; } else if ('sf-dump-expanded' == oldClass) { arrow = '&#9654;'; newClass = 'sf-dump-compact'; } else { return false; } a.lastChild.innerHTML = arrow; s.className = newClass; if (recursive) { try { a = s.querySelectorAll('.'+oldClass); for (s = 0; s < a.length; ++s) { if (a[s].className !== newClass) { a[s].className = newClass; a[s].previousSibling.lastChild.innerHTML = arrow; } } } catch (e) { } } return true; }; return function (root) { root = doc.getElementById(root); function a(e, f) { addEventListener(root, e, function (e) { if ('A' == e.target.tagName) { f(e.target, e); } else if ('A' == e.target.parentNode.tagName) { f(e.target.parentNode, e); } }); }; function isCtrlKey(e) { return e.ctrlKey || e.metaKey; } addEventListener(root, 'mouseover', function (e) { if ('' != refStyle.innerHTML) { refStyle.innerHTML = ''; } }); a('mouseover', function (a) { if (a = idRx.exec(a.className)) { try { refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}'; } catch (e) { } } }); a('click', function (a, e) { if (/\bsf-dump-toggle\b/.test(a.className)) { e.preventDefault(); if (!toggle(a, isCtrlKey(e))) { var r = doc.getElementById(a.getAttribute('href').substr(1)), s = r.previousSibling, f = r.parentNode, t = a.parentNode; t.replaceChild(r, a); f.replaceChild(a, s); t.insertBefore(s, r); f = f.firstChild.nodeValue.match(indentRx); t = t.firstChild.nodeValue.match(indentRx); if (f && t && f[0] !== t[0]) { r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); } if ('sf-dump-compact' == r.className) { toggle(s, isCtrlKey(e)); } } if (doc.getSelection) { try { doc.getSelection().removeAllRanges(); } catch (e) { doc.getSelection().empty(); } } else { doc.selection.empty(); } } }); var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), elt = root.getElementsByTagName('A'), len = elt.length, i = 0, t = []; while (i < len) t.push(elt[i++]); elt = root.getElementsByTagName('SAMP'); len = elt.length; i = 0; while (i < len) t.push(elt[i++]); root = t; len = t.length; i = t = 0; while (i < len) { elt = root[i]; if ("SAMP" == elt.tagName) { elt.className = "sf-dump-expanded"; a = elt.previousSibling || {}; if ('A' != a.tagName) { a = doc.createElement('A'); a.className = 'sf-dump-ref'; elt.parentNode.insertBefore(a, elt); } else { a.innerHTML += ' '; } a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; a.innerHTML += '<span>&#9660;</span>'; a.className += ' sf-dump-toggle'; if ('sf-dump' != elt.parentNode.className) { toggle(a); } } else if ("sf-dump-ref" == elt.className && (a = elt.getAttribute('href'))) { a = a.substr(1); elt.className += ' '+a; if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { a = a != elt.nextSibling.id && doc.getElementById(a); try { t = a.nextSibling; elt.appendChild(a); t.parentNode.insertBefore(a, t); if (/^[@#]/.test(elt.innerHTML)) { elt.innerHTML += ' <span>&#9654;</span>'; } else { elt.innerHTML = '<span>&#9654;</span>'; elt.className = 'sf-dump-ref'; } elt.className += ' sf-dump-toggle'; } catch (e) { if ('&' == elt.innerHTML.charAt(0)) { elt.innerHTML = '&hellip;'; elt.className = 'sf-dump-ref'; } } } } ++i; } }; })(document); </script> <style> pre.sf-dump { display: block; white-space: pre; padding: 5px; } pre.sf-dump span { display: inline; } pre.sf-dump .sf-dump-compact { display: none; } pre.sf-dump abbr { text-decoration: none; border: none; cursor: help; } pre.sf-dump a { text-decoration: none; cursor: pointer; border: 0; outline: none; }pre.sf-dump{background-color:#fff; color:#222; line-height:1.2em; font-weight:normal; font:12px Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:100000}pre.sf-dump .sf-dump-num{color:#a71d5d}pre.sf-dump .sf-dump-const{color:#795da3}pre.sf-dump .sf-dump-str{color:#df5000}pre.sf-dump .sf-dump-cchr{color:#222}pre.sf-dump .sf-dump-note{color:#a71d5d}pre.sf-dump .sf-dump-ref{color:#a0a0a0}pre.sf-dump .sf-dump-public{color:#795da3}pre.sf-dump .sf-dump-protected{color:#795da3}pre.sf-dump .sf-dump-private{color:#795da3}pre.sf-dump .sf-dump-meta{color:#b729d9}pre.sf-dump .sf-dump-key{color:#df5000}pre.sf-dump .sf-dump-index{color:#a71d5d}</style><pre class=sf-dump id=sf-dump-1746454248 data-indent-pad="  ">"<span class=sf-dump-str title="5 characters">hello</span>"
</pre><script>Sfdump("sf-dump-1746454248")</script>
' is not a valid HTTP header field value.
    at Error (native)
    at http://localhost:8090/js/vendor.js:11442:17
    at forEach (http://localhost:8090/js/vendor.js:335:20)
    at http://localhost:8090/js/vendor.js:11440:7
    at sendReq (http://localhost:8090/js/vendor.js:11293:9)
    at serverRequest (http://localhost:8090/js/vendor.js:11003:16)
    at processQueue (http://localhost:8090/js/vendor.js:15627:28)
    at http://localhost:8090/js/vendor.js:15643:27
    at Scope.$eval (http://localhost:8090/js/vendor.js:16895:28)
    at Scope.$digest (http://localhost:8090/js/vendor.js:16711:31)(anonymous function) @ angular.js:13294(anonymous function) @ angular.js:10007processQueue @ angular.js:15635(anonymous function) @ angular.js:15643Scope.$eval @ angular.js:16895Scope.$digest @ angular.js:16711Scope.$apply @ angular.js:17003(anonymous function) @ angular.js:24679defaultHandlerWrapper @ angular.js:3417eventHandler @ angular.js:3405
angular.js:13294 Broken interceptor detected: Config object not supplied in rejection:
 https://github.com/chieffancypants/angular-loading-bar/pull/50
jadjoubran commented 8 years ago

Hi @iannazzi Thanks for testing this :smile: Can you please open the satellizer.config.js file and remove the httpInterceptor function? all 3 lines.

I need to remove them anyway, but I want to see if that's the issue

iannazzi commented 8 years ago

I don't see a change in the error...

export function SatellizerConfig($authProvider) {
    'ngInject';

    $authProvider.loginUrl = '/api/auth/login';
    $authProvider.signupUrl = '/auth/signup';

}
jadjoubran commented 8 years ago

Btw it's working for me in the latest update.. Maybe you're a few commits behind? I recently made a lot of fixes

iannazzi commented 8 years ago

I think I am only behind the last three commits you just pushed up.... working in the changes manually as our projects are a bit different and also my lack of knowledge of git.

I am implementing satellizer via https://www.toptal.com/angular-js/facebook-login-angularjs-app-satellizer....almost done for safari, still stuck with this error on chrome

What module would I attach this run statement to?

app.run(function ($rootScope, $state, $auth) {
  $rootScope.$on('$stateChangeStart',
    function (event, toState) {
      var requiredLogin = false;
      // check if this state need login
      if (toState.data && toState.data.requiredLogin)
        requiredLogin = true;

      // if yes and if this user is not logged in, redirect him to login page
      if (requiredLogin && !$auth.isAuthenticated()) {
        event.preventDefault();
        $state.go('login');
      }
    });
});
jadjoubran commented 8 years ago

hmm yeah.. try to apply the last 3 commits because it's working fine on chrome here.. you can maybe import it in the index.routes.js

iannazzi commented 8 years ago

Chrome is working. I first verified it was not an issue with any of the libraries. I am using bootstrap which pulls in jquery. I then used safari and firefox today as I worked on satellizer auth setup and went back later and checked it on chrome and it was fixed. There was a hard cpu restart in there as well. In the end I changed index.moudles.js to include a .run statement to protect a route if we define that in our controller data. It all seems to be working great, including some JWT custom claims. So who knows why chrome was not working and now is?

Here is how I implemented satellizer index.module.js


var app = angular.module('app', [
    'app.filters',
    'app.services',
    'app.components',
    'app.routes',
    'app.config',
    'partialsModule'
]);

angular.module('app.routes', []);
angular.module('app.filters', []);
angular.module('app.services', []);
angular.module('app.config', []);
angular.module('app.components', [
    'ui.router', 'ngMaterial', 'ngStorage', 'restangular', 'angular-loading-bar','satellizer'
]);

app.run(function ($rootScope, $state, $auth) {
    $rootScope.$on('$stateChangeStart',
        function (event, toState) {
            var requiredLogin = false;
            if (toState.data && toState.data.requiredLogin)
            {
                requiredLogin = true;
            }
            if (requiredLogin && !$auth.isAuthenticated()) {
                event.preventDefault();
                $state.go('app.login');
            }
        });
});

and then the protected route is defined using data: RoutesConfig.js

 .state('app.dashboard', {
            url: '/dashboard',
            views: {
                'main@': {
                    templateUrl: getView('dashboard')
                }
            },
            data: {requiredLogin: true}
        })

And the login funcitonality loginComponent.js

class LoginController{
    constructor($scope, $auth, $state,) {
        'ngInject';

        this.$auth = $auth;
        this.$scope = $scope;
        this.$state = $state;
        $scope.vm.company = 'Embrasse-moi';
        $scope.vm.username = '123456';
        $scope.vm.password = '11111111';

    }

    login(){
        var user = {
            company: this.company,
            username: this.username,
            password: this.password
        };
        var me = this;
        this.$auth
            .login(user)
            .then(function (response) {
                console.log(response);
                me.$auth.setToken(response.data);
                me.$state.go('app.dashboard');
            })
            .catch(function (response) {
                console.log("error response", response);
            })
    };

}
export const LoginComponent = {
    templateUrl: './views/app/components/login/login.component.html',
    controller: LoginController,
    controllerAs: 'vm',
    bindings: {}
}

Im Not sure I want a component as well as a page for pages like Home and Dashboard. I'm wondering about creating index.controller.js which pulls in controllers like app/pages/home/home.page.js.

jadjoubran commented 8 years ago

Looks good! A few improvements if you're interested: 1) .run would look nicer in the index.route.js 2) check my new improvements to stallizer.config and login component :smile:

I tend to do everything in components if this is a big project

iannazzi commented 8 years ago

@jadjoubran Dang I am getting this error again after manually pulling in the changes from the past 10 days.

jadjoubran commented 8 years ago

@iannazzi can you send some code? where the issue is firing

iannazzi commented 8 years ago

@jadjoubran Error is firing at login submit.

First rebooted the machine, after reading notes from above.

Second, I am testing in safari and chrome using local php serve and docker VM. I have three cases giving me the following error and one case of error on chrome using docker vm with a Failed to load resource: the server responded with a status of 422 (Unprocessable Entity) error

angular.js:13424 Error: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'Bearer <!doctype html>
<html ng-app="app" ng-strict-di>
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="apple-touch-icon" sizes="57x57" href="img/icons/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="img/icons/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="img/icons/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="img/icons/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="img/icons/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="img/icons/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="img/icons/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="img/icons/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="img/icons/apple-icon-180x180.png">
    <link rel="icon" type="image/png" sizes="192x192"  href="img/icons/android-icon-192x192.png">
    <link rel="icon" type="image/png" sizes="32x32" href=img/icons"/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="96x96" href=img/icons"/favicon-96x96.png">
    <link rel="icon" type="image/png" sizes="16x16" href=img/icons"/favicon-16x16.png">
    <link rel="manifest" href="ing/icons/manifest.json">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="img/icons/ms-icon-144x144.png">
    <meta name="theme-color" content="#ffffff">

    <link rel="stylesheet" href="/build/css/vendor-f3b9058a18.css">
    <link rel="stylesheet" href="/build/css/app-2969aa409a.css">

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">

    <title ng-bind="header"></title>

    <!--[if lte IE 10]>
    <script type="text/javascript">document.location.href = '/unsupported-browser'</script>
    <![endif]-->
</head>
<body id="bootstrap-overrides">

    <div ui-view="header"></div>
    <div ui-view="main"></div>
    <div ui-view="footer"></div>

    <script src="/build/js/vendor-941d193443.js"></script>
    <script src="/build/js/partials-b04ca4887a.js"></script>
    <script src="/build/js/app-a84cfcc2f1.js"></script>

            <script type="text/javascript">
        document.write('<script src="'+ location.protocol + '//' + (location.host.split(':')[0] || 'localhost') +':35729/livereload.js?snipver=1" type="text/javascript"><\/script>')
    </script>
    </body>
</html>
' is not a valid HTTP header field value.

Verified backend works through curl

    curl laravel.dev/api/auth/login -H "Content-Type: application/json" -X POST -d '{"company":"Embrasse-moi","username":"admin","password":"xxx"}'

curl localhost:8090/api/auth/login -H "Content-Type: application/json" -X POST -d '{"company":"Embrasse-moi","username":"admin","password":"xxx"}'

login function

  login() {
        var user = {
            company: this.company,
            email: this.email,
            password: this.password
        };
        this.$auth.login(user)
            .then((response) => {
            this.$auth.setToken(response.data);
        this.$rootScope.$broadcast('loginEvent', { loginText: 'logout' });
        this.$state.go('app.dashboard');

        this.ToastService.show('Logged in successfully.');
    })
    .catch(this.failedLogin.bind(this));
    }

    failedLogin(response) {
        if (response.status === 422) {
            for (var error in response.data.errors) {
                return this.ToastService.error(response.data.errors[error][0]);
            }
        }
        this.ToastService.error(response.statusText);
    }

Looked though satelizer seems ok. Maybe I'll take a look at restangular. In the meantime I am working the migration in the opposite direction, cloning your repository and moving my code in there. Not sure the best approach

jadjoubran commented 8 years ago

The 422 means a validation issue.. The second issue you showed shows either a misconfigured satellizer (can you show me your satellizer.config) or wrong routes (can you show me your routes.php)

iannazzi commented 8 years ago

satellizer config:

export function SatellizerConfig($authProvider) {
    'ngInject';

    $authProvider.httpInterceptor = function() {
        return true;
    }

    $authProvider.loginUrl = '/api/auth/login';
    $authProvider.signupUrl = '/api/auth/register';
    $authProvider.tokenRoot = 'data';//compensates success response macro

}

Routes: (got a bunch of stuff to clean up here... but should be fine???)

export function RoutesConfig($stateProvider, $urlRouterProvider) {
    'ngInject';

    var getView = function (viewName) {
        return './views/app/pages/' + viewName + '/' + viewName + '.page.html';
    };

    $urlRouterProvider.otherwise('/');

    $stateProvider
        .state('app', {
            abstract: true,
            views: {
                header: {
                    templateUrl: getView('header')
                    //controller: 'headerController'
                },
                footer: {
                    templateUrl: getView('footer')
                },
                main: {}
            }

        })
        .state('app.home', {
            url: '/',

            views: {
                'main@': {
                    templateUrl: getView('home'),
                    controller: function ($rootScope, $scope, $auth) {
                        $rootScope.header = "Craiglorious";
                        // Page.setTitle('Craiglorious');
                        $scope.test = '123';
                        $scope.company = 'Craiglorious';
                        $scope.params = "params";
                        $scope.data = "data";
                        $scope.items = ['a', 'list'];
                        $scope.isAuthenticated = function () {
                            return $auth.isAuthenticated();
                        };
                    }
                }

            }

        })
        .state('app.create_todo', {
            url: '/create-todo',
            views: {
                'main@': {
                    templateUrl: getView('create_todo')
                }
            }
        })
        .state('app.login', {
            url: '/login',
            views: {
                'main@': {
                    templateUrl: getView('login')
                }
            }
        })
        .state('app.register', {
            url: '/register',
            views: {
                'main@': {
                    templateUrl: getView('register')
                }
            }

        })
        .state('app.dashboard', {
            url: '/dashboard',
            views: {
                'main@': {
                    templateUrl: getView('dashboard'),  
                    //controller: 'dashboardController',
                }
            },
            data: {auth: true}
        })

    ;
}
iannazzi commented 8 years ago

BTW I have your most current version + docker VM working fine, so the issue is somewhere in how I pulled in the updates. It is troubling that I can't get enough info to debug and fix.

jadjoubran commented 8 years ago

I don't see anything wrong here.. So which error are you getting right now? I got a bit lost when you told me there were 2 errors

If you're getting this one Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'Bearer <!doctype html> then please send me a screenshot of this request in your chrome's Network tab

iannazzi commented 8 years ago

@jadjoubran

I believe this has something to do with local environment. I have it working great this morning using my version of laradock, which I highly recommend pulling into the project.

The 422 error I received yesterday, as reported above, was my probably error, passing email instead of username , so for chrome connected to the docker VM, it was probably working fine.

Using php artisan serve --port=8090 generates the error:

screen shot 2016-04-09 at 10 03 57 am

The request never actually gets sent.... there is nothing in the network tab of the javascript console.

jadjoubran commented 8 years ago

@iannazzi take a look at this issue Let's follow their suggestion.. Can you try and disable other packages one by one? There's the loading bar included out of the box.. and maybe you added something else as well?

iannazzi commented 8 years ago

@jadjoubran funny I was looking at that issue yesterday. The problem is bootstrap. Took it out of bower.json, cleared out bower_components, bower install, gulp, php artisan serve --port=8090 reloaded the page, it is ugly but it works.

I figured bootstrap and angular would eventually not get along, most likely due to jquery. It looks like I should be using ui-bootstrap. Just reminding myself that I put in bootstrap because it took me minutes to complete what angular-material was taking me days without completion.

Ok thanks again!

jadjoubran commented 8 years ago

Oh okay! Sure :smile: