Created by @barglm in Q&As
@barglm
@barglm

I have a question, I have web with modules [client, admin, open]. At first, client visits open module, here is sign in form and some other parts, than he logs. Due to a lot of scripts, each module has own layout.

How to solve reload of whole body and head tag in case of changing the module. Also how to change title of each page? When I add snippet to title tag, it does not work... it is replaced and in the same second replaced back to original page title.

Maybe somehow on success force classic reload? But how to do it except adding data-ajax=false on the sign in button, but adding it into form success action?

Thanks

@jahudka
@jahudka

Hi, I suspect you're doing a redirect after a sign in, correct? If you do, then you can just disable AJAX for the redirect - Nittro will then do a full-page redirect. You can do this by setting $presenter->payload->allowAjax = false;, which you can shorten to $presenter->disallowAjax(); if you use nittro/nette-bridges base presenter or PresenterUtils trait.

As for the page title: this is a long-known issue - Nittro manages the page title on its own and expects to find it in the response payload under the title key - so while it won't prevent you from making <title> a snippet, it will ultimately override it by whatever is in payload.title, defaulting to the current page title. There's currently no easy way to make a <title> snippet work the way you want it to.. you'll have to assign your title to a variable and add that variable to payload e.g. in afterRender().

@barglm
@barglm

ad1) thanks, works like a magic

ad2) wtf,... I am screwed,... we have title defined as:

<title>{ifset title}{include title|trim|stripHtml} | {_'IncParadise'}{/ifset}</title>

And the title is set in each latte file as a block,... I will try to create some processing to get the block content in afterrender. Or rewrite the code, but thanks

@jahudka
@jahudka

Well you could also hot-patch the current behaviour in client side code - it's not hard really, but it'd require you to build Nittro yourself - which you might be doing already, in which case you're golden. All you need to do is define a service which listens for the history-save event of all page transactions and override the title there using whatever is the current document.title - since snippets are guaranteed to be applied before the history-save event occurs document.title will already reflect whatever came in the <title> snippet. This is how you'd do it: create a file somewhere in your app, let's call it TitleHotPatch.js:

_context.invoke('App', function() {
    var TitleHotPatch = _context.extend(function(page) {
        this._ = {
            page: page
        };

        this._.page.on('transaction-created', this._handleTransaction.bind(this));
    }, {
        _handleTransaction: function(evt) {
            evt.data.transaction.on('history-save', this._handleHistorySave.bind(this));
        },
        _handleHistorySave: function(evt) {
            evt.data.title = document.title;
        }
    });

    _context.register(TitleHotPatch, 'TitleHotPatch');
});

Now add titleHotPatch: "App.TitleHotPatch()!" to the services section of your bootstrap configuration and rebuild :-)

@barglm
@barglm

I have to admit, you are a great developer beyond my comprehension, but I think I may use it. Thank you, also thank you for the workshop last week.

@jahudka
@jahudka

You're welcome 😊 but I'm not that great, if I were I'd have developed a library that people can use without running into issues like these 😄

@barglm
@barglm

I have a problem with the script, it is not applied. Actually, the transaction-created event is not called, I added console.log and not a single time it was used. Is there some extension which needs to be enabled?

@jahudka
@jahudka

No, the transaction-created event is emitted by the page service which is pretty much a core part of Nittro, nothing would work if this service wasn't running properly - is it possible that you omitted the ! symbol at the end of the service definition in your bootstrap config? It's a shorthand to make the service run at container init; if it's absent the container won't create the service at all, because it's lazy and nothing else depends on it. In your Gulpfile (or wherever you're specifying options for the Nittro builder) you should have an options map with keys like vendor, base and so on - along with the key bootstrap, which specifies bootstrap options. If this were the only service you're registering, your bootstrap section could look like this:

var builder = new nittro.Builder({
    // vendor: ...
    // base: ...
    bootstrap: {
        services: {
            titleHotPatch: 'App.TitleHotPatch()!'
        }
    }
});
@barglm
@barglm

It should be ok

const nittroBuilder = new nittro.Builder({
    base: {
        di: true,
        page: true,
        forms: true,
        flashes: true,
    },
    extras: {
        dialogs: true,
        confirm: true,
        checklist: true,
        paginator: true
    },
    libraries: {
        js: [
            'src/assets/js/BootstrapErrorRenderer.js',
            'src/assets/js/TitleHotPatch.js'
        ],
    },
    bootstrap: {
        params: {
            dialogs: {
                baseZ: 6000
            }
        },
        services: {
            formErrorRenderer: 'App.Forms.BootstrapErrorRenderer()',
            titleHotPatch: "App.TitleHotPatch()!"
        }
    },
    stack: true
});

gulp.task('nittro:js', function () {
    return nittro('js', nittroBuilder)
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(except(/\.min\.js$/i, uglify({ compress: true, mangle: false })))
        .pipe(concat('nittro.min.js'))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('public/js'));
});
@jahudka
@jahudka

That's really weird.. Okay, to debug: open your browser's developer tools, switch to Console view, paste the following line and press Enter:

_context.lookup('di')._

You should get an interactive object dump with the keys params, serviceDefs, services and factories at the top level; you should be able to find the keys page and titleHotPatch under the serviceDefs key as well as under the services key. If titleHotPatch is missing in either of those places, then there's an issue with your build somewhere; if it's there then there's something weirder going on.

@barglm
@barglm

So, the page is there, also the formErrorRenderer which you send me after the workshop, but titleHotPatch is not present. This is strange, in the build, I can see

_context.invoke("App", function () {
    var TitleHotPatch = _context.extend(function (page) {
        this._ = {page: page}, this._.page.on("transaction-created", this._handleTransaction.bind(this))
    }, {
        _handleTransaction: function (evt) {
            evt.data.transaction.on("history-save", this._handleHistorySave.bind(this))
        }, _handleHistorySave: function (evt) {
            evt.data.title = document.title
        }
    });
    _context.register(TitleHotPatch, "TitleHotPatch")
});

_context.invoke(function (Nittro) {
    var builder = new Nittro.DI.ContainerBuilder({
        params: {dialogs: {baseZ: 6e3}},
        extensions: {
            ajax: "Nittro.Ajax.Bridges.AjaxDI.AjaxExtension()",
            page: "Nittro.Page.Bridges.PageDI.PageExtension()",
            forms: "Nittro.Forms.Bridges.FormsDI.FormsExtension()",
            flashes: "Nittro.Flashes.Bridges.FlashesDI.FlashesExtension()",
            dialogs: "Nittro.Extras.Dialogs.Bridges.DialogsDI.DialogsExtension()",
            confirm: "Nittro.Extras.Confirm.Bridges.ConfirmDI.ConfirmExtension()",
            checklist: "Nittro.Extras.CheckList.Bridges.CheckListDI.CheckListExtension()",
            paginator: "Nittro.Extras.Paginator.Bridges.PaginatorDI.PaginatorExtension()"
        },
        services: {formErrorRenderer: "App.Forms.BootstrapErrorRenderer()", titleHotPatch: "App.TitleHotPatch()!"},
        factories: {}
    });
    this.di = builder.createContainer(), this.di.runServices()
});
@jahudka
@jahudka

And there are no errors in console about TitleHotPatch not found in _context or similar? Could you send me your package.json, package.lock and gulpfile.js? You can paste them here or send them over email.

Sign in to post a reply