Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 01, 2016 @ 09:44
    Jeroen Breuer
    0

    Check if node has been saved and published in property editor

    Hello,

    I'm creating a property editor which shows the urls of the current node. It does the exact same thing as Link to document on the Properties tab, but our users want to see the urls on the first tab instead of the last tab.

    I've already got it working, but the problem is that if you update the node name (or in this example the Url segment) the property editor isn't updated and still shows the old urls until you reopen the node. Can I check in the property editor if the save and publish button has been clicked and everything is updated?

    enter image description here

    Jeroen

  • Dave Woestenborghs 3344 posts 11303 karma points MVP 6x admin c-trib
    Feb 01, 2016 @ 09:53
    Dave Woestenborghs
    0

    Hi Jeroen,

    You can implement a event handler for this in your controller

    $scope.model.onValueChanged = function (newVal, oldVal) {
              //update the display val again if it has changed from the server
    
            };
    

    Dave

  • Søren Kottal 576 posts 3756 karma points MVP 3x c-trib
    Feb 01, 2016 @ 09:53
    Søren Kottal
    0

    Maybe you can save the editorState in another variable on load, and then check when something changes? Not sure if it's updated though.

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 01, 2016 @ 10:03
    Lars-Erik Aabech
    0

    Hi guys,

    @Dave's answer is probably "good enough", but I think it'll trigger on save too.

    If you couldn't find anything on the scope.content graph, I'd make a directive that attaches a DOM eventhandler to the save & publish button(s). Push that event to an observable angular service and listen to it in the property-editor.
    (I'm sure you know how to. :) )

    Lars-Erik

    [edit] PS. There really is a noticeable lack of events in the content-editor "scope". Not sure how to organize, but would be good to add some input on issues.umbraco.org.

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 01, 2016 @ 11:44
    Jeroen Breuer
    0

    Hello,

    I tried onValueChanged, but that never is hit. Probably because nothing is changed. Not even after saving.

    I guess I could attach to the save & publish buttons, but I was hoping there would be a better way.

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 01, 2016 @ 12:02
    Lars-Erik Aabech
    0

    I added a few suggestions to the issue tracker.
    Feel free to comment/vote.

    http://issues.umbraco.org/issue/U4-7874

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 01, 2016 @ 15:36
    Jeroen Breuer
    0

    Voted :-). Even if I can hook into the save & publish eventhandler is there a way to know when it's done posting?

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 01, 2016 @ 16:34
    Lars-Erik Aabech
    0

    This is quickly becoming an ugly hack, but you could always intercept the http call. 😊

    // alternatively, register the interceptor via an anonymous factory
    $httpProvider.interceptors.push(function($q) {
      return {
    
        'response': function(response) {
           // check if looks like publish response
        }
      };
    });
    

    Pasted from https://docs.angularjs.org/api/ng/service/$http

  • Ian 178 posts 751 karma points
    Feb 01, 2016 @ 18:03
    Ian
    0

    mm, could try this (reference to first property on first tab only here as an example)

    $scope.$on("formSubmitted", function () {
            console.log(editorState.current.tabs[0].properties[0].value)
        });
    
  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 01, 2016 @ 19:59
    Lars-Erik Aabech
    100

    So this annoyed the hell out of me. :)

    Here's a working solution.

    Testing scope.message output:

    model changed Mon Feb 01 2016 20:52:08 GMT+0100 (W. Europe Standard Time)
    published to server Mon Feb 01 2016 20:52:22 GMT+0100 (W. Europe Standard Time)
    saved to server Mon Feb 01 2016 20:52:36 GMT+0100 (W. Europe Standard Time)
    

    TestController is my property editor controller.
    The service and interceptor can live elsewhere.

    Controller:

    (function (ng) {
        var umbraco = ng.module("umbraco");
    
        function TestController(scope, httpEvents) {
    
            scope.$watch("model", function () {
                // does not get destroyed, nor changed on save &| publish.
                scope.message = (scope.message || "") + "\n" +
                    "model changed " + new Date();
            }, true);
    
            function posted(type) {
                scope.message = (scope.message || "") + "\n" +
                    type + " to server " + new Date();
            }
    
            httpEvents.register(posted);
    
            scope.$on("$destroy", function() {
                httpEvents.unregister(posted);
            });
    
        }
    
        umbraco.controller("test-controller", [
            "$scope",
            "content-events-service",
            TestController
        ]);
    
    }(angular));
    

    Service and interceptor:

    (function (ng) {
        var umbraco = ng.module("umbraco");
    
        function ContentEventsService() {
            var listeners = [];
    
            this.register = function (listener) {
                listeners.push(listener);
            }
    
            this.unregister = function (listener) {
                var index = listeners.indexOf(listener);
                listeners.splice(index, 1);
            }
    
            this.raise = function (type) {
                var i;
                for (i = 0; i < listeners.length; i++) {
                    listeners[i](type);
                }
            }
        }
    
        function createInterceptor(httpEvents, q) {
            return {
                'response': function(response) {
                    if (response.config.url === "/umbraco/backoffice/UmbracoApi/Content/PostSave") {
                        if (response.config.data.value.action === "publish") {
                            httpEvents.raise("published");
                        } else {
                            httpEvents.raise("saved");
                        }
                    }
    
                    return response || q.when(response);
                }
            };
        }
    
        umbraco.service("content-events-service", [
            ContentEventsService
        ]);
    
        umbraco.factory("content-http-interceptor", [
            "content-events-service",
            "$q",
            createInterceptor
        ]);
    
        umbraco.config([
            "$httpProvider", function(httpProvider) {
                httpProvider.interceptors.push("content-http-interceptor");
            }
        ]);
    
    
    }(angular));
    

    Hope you can use it.
    Looks like it solves a couple of my own annoyances too, so thanks for asking the question. :D

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 02, 2016 @ 12:12
    Jeroen Breuer
    0

    Hi,

    Thanks for the example. I'm still pretty new to Angular. I added the service and interceptor and than updated my property editor controller. The problem is that when I'm trying ot use httpEvents in my controller I get the following exception:

    Unknown provider: httpEventsProvider <- httpEvents
    

    Do I need to do something extra for the httpEvents?

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 02, 2016 @ 12:45
    Lars-Erik Aabech
    1

    And here I thought you were a wiz. with anything before even knowing about it. ;)

    I guess you haven't caught on to the whole dependency injection form in angular? If the service is registered as such:

    umbraco.service("content-events-service", [
        ContentEventsService
    ]);
    

    You have to inject it in your controller as such:

    umbraco.controller("test-controller", [
        "$scope",
        "content-events-service",
        function(scope, httpEvents) {
        }
    ]);
    

    See the string matching the name of the service?

    In the controller constructor, you can now call it whatever you want (httpEvents).
    But if you don't use the array/string injection form, you'll have to name the service something legal for JavaScript, and you can't minify the code.

    More info here: https://docs.angularjs.org/guide/di

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 02, 2016 @ 13:15
    Jeroen Breuer
    0

    Thanks for your help! I am familiar with dependency injection in angular, but most of the time it just worked automagically ;-). I got it working now and the url preview gets updated when the node name or url segment is updated.

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 02, 2016 @ 13:17
    Lars-Erik Aabech
    0

    Great! :)

    There are some events being thrown around in Umbraco core angular services, but it's pretty undocumented and probably lacks this one. Hopefully someone gives it some love sooner or later.

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 10, 2016 @ 14:56
    Jeroen Breuer
    0

    Hi Lars,

    I've had a closer look at the example you provided which I've marked as the solution. It's a lot of code just to check when it's "published". Do I really need all this code? I might release the url preview as a package so I want the code to be clean and understandable. Could you maybe add some comments to your example to what it does and why?

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Feb 10, 2016 @ 15:01
    Lars-Erik Aabech
    0

    Well, about the urls to the content..
    If you recurse through $scope.$parent, you'll eventually find parent.content.
    That's the content you're editing, and incidentally it has .urls...

    So the code might be completely useless. ;)

    What my code does though, is to hook into angulars http interceptors, so it fires for any and all http calls made from the backoffice.
    It can be used to detect calls to anything serverside, and fire an event based on the URL or parameters when the reply is received.

    Pretty cool, but might be overkill for your needs if you can pick the urls from the content on the ancestral scope. :D

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Feb 10, 2016 @ 15:51
    Jeroen Breuer
    0

    Hmm maybe that works. The urls are also available on the editorState, but not updated if you change the node name. Think I'll keep it like this because I can hook into the published event. Thanks for explaining.

    Jeroen

  • Jeroen Breuer 4861 posts 12139 karma points MVP 3x admin c-trib
    Jan 19, 2017 @ 11:05
    Jeroen Breuer
    1

    Hello,

    I've released a package which can show the node URLs on any tab: https://our.umbraco.org/projects/backoffice-extensions/url-preview/

    It uses the interceptor technique discussed in this topic.

    Jeroen

  • Lars-Erik Aabech 349 posts 1098 karma points MVP 5x c-trib
    Jan 19, 2017 @ 13:33
    Lars-Erik Aabech
    1

    I can see I totally forgot to update the thread with new knowledge. You don't have to recurse up the scope tree to find content. It's available on the editorState service. If you inject it, you'll have the current content on editorState.current.

    But otherwise, the events are non-existing, so interceptor is the way to go.

  • Laurent Lequenne 121 posts 246 karma points
    Feb 01, 2017 @ 16:12
    Laurent Lequenne
    0

    Hi Lars,

    Any idea how to force validation again with the editorState service or any other way ? I have some editor that changes the node name on the "formSubmitting" event , but actually if the form was invalid (no node name specified) it does not push to the server, even if the validation appears ok after ... I need to push the save button again to make it happen.

Please Sign in or register to post replies

Write your reply to:

Draft