Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

realtebo's avatar

How to append to an element the HTML received via JSON API?

I have an API that returns me a partial a renderer blade and another params as JSON.

{ rendered_view : '<div .... > ....</div>' , nextPageLink : 'https:/....' }

The output come from this code

if ($request->ajax()) {
            $rendered_view = view ('layouts.product_box_drawer', compact(
                'products_to_show'
            ))->render();
            return response()->json([
                'rendered_view'   => $rendered_view,
                'next_page_link'  => $next_page_link,
            ]);
        }

I'm trying to do this

                   Vue.http.get(this.url, {
                        before(request) {
                            if (this.previousRequest) {
                                this.previousRequest.abort();
                            }
                            this.previousRequest = request;
                        }
                    }).then( response => {
                        // success callback
                        console.dir (response.body);
                        this.url = response.body.next_page_link;
                        this.$refs.the_container.append( response.body.rendered_view );
                    }, response => {
                        // error callback

                    });

The problem is with the row

 this.$refs.the_container.append( response.body.rendered_view );

It appends the content of rendered_view, but it's raw html. I mean I see the HTML CODE appended, while I need that browser can RENDER html elements I received. I see on page <div .... > ....</div>.

I need to see my list of products, rendered.

I don't know if the problem is api-side or blade-side.

0 likes
4 replies
realtebo's avatar

Thanks @Reached . But I'm not able to understand how to change my code.

Note that I'm using this strategy now

this.$refs.the_container.append 

Because into the_container I already have the first 30 products, already rendered server-side.

This because when user load the page, the first 30 products are already on the page.

When user scroll down, at a fixed point I trigger ther ajax loading of another set of products. I need to add the new html block to what already is rendered.

So I can't resolve the problem server-side at the first call (a normal get).

I need that on sobsequent ajax call, when Laravel code send me raw html, I can append to what is already on the page.

realtebo's avatar

Yes.. it's working, cross-browser (Edge, ie11, chrome, ff, safari) but I'am disgusted of the solution ....

I added also a throttle, triggered on leading, and two controls to avoi overlapping the same requests.

        const family_vue_app = new Vue({

            {{-- Defined int layouts.app.balde --}}
            el: '#app',

            data: {
              'url'     : '{!! $next_page_link !!}',
              'loading' : false,
            },

            methods: {
                handleScroll :  _.throttle(
                    {{-- Do not use arrow functions here, IE11 will complain !--}}
                    function() {
                        let trigger_pos = document.getElementById('load_more').getBoundingClientRect().top;
                        if (trigger_pos < 3000) {
                            family_vue_app.callAjax();
                        }
                    }, 1000, { leading: true}
                ),
                callAjax : function () {

                    Vue.http.get(family_vue_app.url, {
                        before : function (request) {
                            if (this.previousUrl === family_vue_app.url) {
                                console.log ('aborting previous request [same url] ');
                                this.previousRequest.abort();

                            }
                            if (this.previousRequest) {
                                console.log ('aborting previous request [another request is alive] ');
                                this.previousRequest.abort();
                            }
                            family_vue_app.loading = true;
                            this.previousRequest = request;
                            this.previousUrl = family_vue_app.url;
                        }
                    }).then( function (response) {
                        // success callback
                        family_vue_app.url = response.body.next_page_link;
                        if (family_vue_app.url === null) {
                            window.removeEventListener('scroll', family_vue_app.handleScroll);
                        }
                        document.getElementById('family_boxes_container').innerHTML += response.body.rendered_view;
                        this.previousRequest = null;
                        family_vue_app.loading = false;

                    }, function(response) {
                        // error callback

                    });
                }

            },
            created : function () {
                window.addEventListener('scroll', this.handleScroll);
            },
            destroyed : function () {
                window.removeEventListener('scroll', this.handleScroll);
            }
        });

Please or to participate in this conversation.