Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs $location.path only updates URL on second click

Tags:

angularjs

The site that I'm working on has a custom CMS, and I'm using angularjs for inline page editing. The database stores HTML used to generate the pages, so I can't strictly use client-side templates and models.

I'm not using HTML5 pushState, so the URLs are like example.com/page#/widget/1/edit or example.com/page#/widget/new, and my current issue is that when I submit a form to edit a widget or add a widget, then I want the page to reload its content via injecting HTML into the DOM and change the URL to the default, which I'm trying with $location.path('/').

My current implementation has multiple issues (which you'll see in the demo), one of which is that in my form submit() callback, changing $location.path only changes the URL on a second form button click. I also try to change the URL which I click 'Delete', and that doesn't work either.

http://jsfiddle.net/sZrer/1

customPage.controller('PageEditCtrl', function($scope, $http, $routeParams, $location, $route, $compile, PageState) {
    var widgetId = $routeParams.id || widgetCount + 1;

    $scope.pageState = PageState;
    $scope.widget = { id: widgetId, name: 'Widget ' + widgetId };
    $scope.submit = function() {
      if ($scope.widget.id > widgetCount) widgetCount += 1;
      setTimeout(function() {
        var element = $compile(genHtml())($scope);
        angular.element('#page-content').html(element);
        $location.path('/');
      }, 100);
    };
  });
like image 826
joshm1 Avatar asked Feb 15 '23 20:02

joshm1


1 Answers

setTimeout() doesn't mix well with Angular (Angular uses an event loop in which it checks for changes to models, but to be able to do that it has to be able to control all parts of your app; setTimeout() is beyond the control of Angular, and when any changes to Angular-parts of your app are made in a setTimeout-handler, it usually takes another 'round' of the Angular event loop before those changes are picked up).

If you replace it with Angular's own $timeout() (be sure to also inject it), it works better (jsfiddle).

like image 149
robertklep Avatar answered Mar 04 '23 12:03

robertklep