[DevTip] Custom list-view for mobile (pure client side)

One of Frappe’s key strengths is its customizabiliity. The framework is designed from the bottom up to empower users, and over the last few versions especially we have better and better hooks at our disposal to do this quickly and cleanly. A lot of this power seems to be relatively unknown, however, so under the “DevProTip” tag I’m trying to start sharing any cool things I’m figuring out.

In my organization, we do a lot of work in the field, and being able to access records quickly is important. The mobile list view is fairly minimalist in its presentation, showing only document name and a colored dot for status. We really wanted to add a bit more data to the mobile view, and it turned out to be quite simple to do.

Here’s the final result, showing an extra “details” line with field variables each row:

To get there, we’re going to create a new client script, for the DocType: “Issue” and Apply To: List. In that script, include the code below.


// first, we'll extend the base ListView class described here:
// https://github.com/frappe/frappe/blob/e8c1a27a7a0c66ffad165bb2c6b3fa3d603228c4/frappe/public/js/frappe/list/list_view.js#L6
frappe.views.ListView = class ListView extends frappe.views.ListView {
    // in this first method override, we'll add an additional parameter
    // and define an extended template for the listview row
    get_list_row_html_skeleton(left = "", right = "", details = "") {
        // check to make sure that we're viewing the right doctype.
        // (this code will load for the Issue doctype, but it will stay in memory when viewing other lists)
        if (this.doctype === "Issue") {
            if (details === null) { details = "" };
    		return `
    			<div class="list-row-container" tabindex="1">
    				<div class="level list-row">
    					<div class="level-left ellipsis">
    						${left}
    					</div>
    					<div class="level-right text-muted ellipsis">
    						${right}
    					</div>
    				</div>
    				<div class="level list-row details-row">Priority: ${details}</div>
    			</div>
    		`;
        }
	}
    // in this second method override, we'll pass the extra variable from our doc object
    // over to our template generator
	get_list_row_html(doc) {
		return this.get_list_row_html_skeleton(
			this.get_left_html(doc),
			this.get_right_html(doc),
			doc.priority
		);
	}
}

// here, we'll add some css to style our new content. Because we're using media queries,
// we can't just style inline and need to add to a style block in the dom.
document.querySelector('style').textContent +=
    `@media (min-width: 768px) { 
        .list-row-container .details-row { display: none; }
    }
    .list-row-container .details-row {
        color: #666;
        padding: 0 55px !important;
    }
    `

This is a very trivial example, of course, but the possibilities are wide open. If you want to customize your list view for one document or all, the option is there.

16 Likes

Thanks for this. Does this work on Version 12? I can’t find a place for “Client Scripts”.

I haven’t tested on v12, but it might work! Pre-13, Client Scripts were called “Custom Scripts”.

Thanks for the response. Yes, and “Custom Scripts” can not be applied to Lists, only Forms :frowning: