How do I reduce view duplication between client and server? - javascript

I'm working on an AJAXy project (Dojo and Rails, if the particulars matter). There are several places where the user should be able to sort, group, and filter results. There are also places where a user fills out a short form and the resulting item gets added to a list on the same page.
The non-AJAXy implementation works fine -- the view layer server-side already knows how to render this stuff, so it can just do it again in a different order or with an extra element. This, however, adds lots of burden to the server.
So we switched to sending JSON from the server and doing lots of (re-)rendering client-side. The downside is that now we have duplicate code for rendering every page: once in Rails, which was built for this, and once in Dojo, which was not. The latter is basically just string concatenation.
So question part one: is there a good Javascript MVC framework we could use to make the rendering on the client-side more maintainable?
And question part two: is there a way to generate the client-side views in Javascript and the server-side views in ERB from the same template? I think that's what the Pragmatic Programmers would do.
Alternatively, question part three: am I completely missing another angle? Perhaps send JSON from the server but also include the HTML snippet as an attribute so the Javascript can do the filtering, sorting, etc. and then just insert the given fragment?

Well, every time you generate HTML snippets on the client and on the server you may end up with duplicated code. There is no good way around it generally. But you can do two things:
Generate everything on the server. Use AHAH when you need to generate HTML snippets dynamically. Basically you ask server to generate an HTML fragment, receive it asynchronously, and plug it in place using innerHTML or any other similar mechanism.
Generate everything on the client (AKA the thick client paradigm). In this case even for the initial rendering you pass data instead of pre-rendered HTML, and process the data client-side using JavaScript to make HTML. Depending on the situation you can use the data island technique, or request data asynchronously. Variant: include it as <script> using JSONP so the browser will make a request for you while loading the page.
Both approaches are very simple and have different set of pros and cons. Sometimes it is possible to combine both techniques within one web application for different parts of data.
Of course you can go for exotic solutions, like using some JavaScript-based server-side framework. In this case you can share the code between the server and the client.

I don't have a complete answer for you; I too have struggled with this on a recent project. But, here is a thought:
Ajax call to Rails
Rails composes the entire grid again, with the new row.
Rails serializes HTML, which is returned to the browser.
Javascript replaces the entire grid element with the new HTML.
Note: I'm not a Rails person, so I'm not sure if those bits fit.

Has anyone tried something like the following? There's redundant data now, but all the rendering is done server-side and all the interaction is done client-side.
Server Side:
render_table_initially:
if nojs:
render big_html_table
else:
render empty_table_with_callback_to_load_table
load_table:
render '{ rows: [
{ foo: "a", bar: "b", renderedHTML: "<tr><td>...</td></tr>" },
{ foo: "c", bar: "d", renderedHTML: "<tr><td>...</td></tr>" },
...
]}'
Client side:
dojo.xhrGet({
url: '/load_table',
handleAs: 'json',
load: function(response) {
dojo.global.all_available_data = response;
dojo.each(response.rows, function(row) {
insert_row(row.renderedHTML);
}
}
});
Storing the all_available_data lets you do sorting, filtering, grouping, etc. without hitting the server.
I'm only cautious because I've never heard of it being done. It seems like there's an anti-pattern lurking in there...

"Perhaps send JSON from the server but also include the HTML snippet as an attribute so the Javascript can do the filtering, sorting, etc. and then just insert the given fragment?"
I recommend keeping the presentation layer on the client and simply downloading data as needed.
For a rudimentary templating engine, you can extend Prototype's Template construct:
http://www.prototypejs.org/api/template
As your client scales and you need a rich and flexible MVC, try PureMVC.
http://puremvc.org/content/view/102/181/

As in regular server side programming you should strive to encapsulate your entities with controls, in your case client side controls that has data properties and also render methods + events.
So for example lets say you have on the page an are that shows tree of employees, effectively you should encapsulate it behavior in a client side class that can get JSON object of the employee list / by default connect to the service and a render method to render the output, events and so on.
In ExtJS its is relatively easy to create these kind of controls - look at this article.

Maybe I'm not fully understanding your problem but this is how I would solve your requirements:
Sort, Filter
It can be done all in JavaScript, without hitting the server. It's a problem of manipulating the table rows, move rows for sorting, hide rows for filtering, there is no need for re-rendering. You will need to mark columns with the data type with custom attributes or extra class names in order to be able to parse numbers or dates.
If your reports are paginated I think it's easier and better to refresh the whole table or page.
Group
I can't help here as I don't understand how will you enable grouping. Are you switching columns to show accumulates? How do you show the data that doesn't support accumulates like text or dates?
New item
This time I would use AJAX with a JSON response to confirm that the new item was correctly saved and possibly with calculated data.
In order to add the new item to the results table I would clone a row and alter the values. Again we don't need to render anything in client-side. The last time I needed something like this I was adding an empty hidden row at the end of the results, this way you will always have a row to clone no matter if the results are empty.

Number 5 in my list of five AJAX styles tends to work pretty well.

Related

how to insert data into pages in nodeJS

I have recently begun to work with NodeJS, after a long time working with PHP, and i'm wondering if there was anything similar to 'echo'. a way of sending the data as parts, allowing me to send my own values in between. For example, writing the structure for a section of a website in html, then using node to send the relevant data inside of the div.
The short answer is "yes". You can repeatedly write to the response object and then call end on it when you are done.
response.setHeader("Content-Type", "text/plain");
response.write("foo");
response.write("bar");
response.write("baz");
response.end();
However, that generally isn't the approach taken for good reason.
Separating your concerns (e.g. splitting "data fetching" and "HTML generation") usually makes things more manageable.
This is why the most common way to build pages server-side with Node.js is to collect all the data for the page into an object and then pass it into a template.
You can, of course, split the data collection logic up into functions in their own modules so you can end up with something like:
const my_data = {
header: get_header_data(request),
content: get_template_name_data(request),
};
response.render('template_name', my_data)
With as much division into smaller chunks are you like.

How do I change my controller so it is decoupled enough from my view?

I'm programming a web app using Spring MVC where I need to create some elements that I cannot create directly through jsp. Specifically all of those that list values that I get from my database, since I cannot create a structure in jsp before knowing its size. Here's how I'm doing it right now:
#RequestMapping(method = RequestMethod.GET)
public ModelAndView getAllEjercicios (...)
...
Table table = new Table("table_ejercicios", "table_ejercicios", new ArrayList<TableHead>(Arrays.asList(tH1, tH2, tH3)), getEjercicioTableContent(ejercicioList));
...
model.put("table", table.getCode());
return new ModelAndView("ejercicio/ejercicio-list", MODEL_NAME, model);
This is my controller method, where Table is a custom class that I created that will return the html code of the table when calling getCode(), using the parameters it was given. The problem with this is that I'm starting to see my Controller is not decoupled enough, since it's passing the view the HTML code of the entire object instead of just the parameters I need in order to build it in my jsp file. Btw, this is not just an issue with this particular table, I have other dropdown lists and things as such in my code.
The problem is that if I use a javascript function which receives the same parameters as my table inside the jsp, I'll have to replicate a lot of code in other views that use similar tables, since I'll have to copy the entire javascript function in each jsp file.
My code works perfectly, it's not a problem of it not working, it's a problem of structure.
What should I do, should I keep my code as it is, or is there a solution I'm not thinking of?
Thanks
The html pages, contains lots of elements, such as tables, forms, dropdown,... . If you generate all UI elements in the backend, your server side code will full of client side coding! This is not a good practice as you already know.
I think the best practice is rendering html pages without any extra UI elements, just html code with data. You can even exclude data from page and fill html elements with data from ajax request. However, your controller will completely free from UI codes. With this approach, your concern is duplication of codes in the client side. This can be solved with generating javascript utilities. For example, you have same html table structure in multiple pages. For doing this, you can write a javascript function for generating table. This function can take some parameters and add dynamic table to every page you need. You can do similar works for other elements such as forms and dropdown.

Is it possible to create a subpage without any file?

I'm a newbie when it comes to PHP. I wrote some JS to make AJAX requests for my project and it worked well, but I don't have any idea how to convert that into PHP.
I've prepared layouts like the following:
mainLayout.php,
userLayout.php,
offerLayout.php,
In those files are some PHP and MySQL parts that build an HTML page.
In Ajax it was easy to navigate between many users using only one page and replacing some divs with data...
But a huge minus was that you couldn't have a single address reference a user profile or the offer (like mywebsite.com/user1).
Now, when I use PHP I want to achieve same layout effect.
How can I avoid creating a thousands of pages (of course even dynamically it seems to be a waste of memory IMO) like user1.php, user2.php, offer1.php, etc.
I don't know how to achieve the effect of being on a site like example.com/user277373.php without creating thousands of files but only one template.
Two solutions I see is either you use GET to parse your data:
http://example.com/?data=1736861
and than access it over the $_GET variable:
$id = $_GET["data"];
($id will be 1736861)
or you use the flight php extension, that will look something like this:
Flight::route('/id/#id', function($id){
echo "ID: $id";
});
and the URL would look like http://example.com/id/1736861. You can also use multiple variables with the flight module.
I hope this helped, Sebastian
Are you familiar with any MVC frameworks? If not, I would highly recommend getting accustomed to the MVC design paradigm. MVC = Model View Controller. From Wikipedia, a short excerpt:
A model stores data that is retrieved according to commands from the controller and displayed in the view.
A view generates new output to the user based on changes in the model.
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its
associated view to change the view's presentation of the model (e.g.,
scrolling through a document).
Two of the key components of MANY frameworks (in pretty much any language), are Routes and Templates. When utilizing a routing system, you're able to specify a template for every page loaded that matches a specific route. For instance, site.com/people/:id where ':id' can be any value in the URL, and be configured to use "person.html" for the HTML output. Note that "person.html" receives variables/data that will dynamically populate content, e.g. <h2>Hello, {{name}}</h2>
So, to clarify, site.com/people/252, site.com/people/12, site.com/people/5, site.com/people/john would all match the site.com/people/:id route path where :id is dynamic, and your system will use ONE TEMPLATE (which you specify) to display all the data. Don't forget, when that route path is met, that's only step 1. You will probably need to take that :id run some database query and pass that data into the template.
A popular micro PHP framework called Slim, might be a good starting point. Here's documentation for its way of handling Routes and Templates:
https://www.slimframework.com/docs/objects/router.html
https://www.slimframework.com/docs/features/templates.html
Slim is commonly used with Twig, a super popular PHP template engine. Here's its website/documentation: http://twig.sensiolabs.org/
And if that wasn't enough, Slim has a super handy First App Walkthrough that will show you routes, database connection, and templates: https://www.slimframework.com/docs/tutorial/first-app.html
Hope this information helps you on your journey – Best of luck!

Spring MVC - Is JSTL Tag JSON Conversion OK?

A psuedo controller method
#RequestMapping("/foo")
public String getFoo(Model model) {
model.add("foo", repo.findFoo());
model.add("bar", repo.findBar());
model.add("barOptions", repo.findBarOptions(bar));
return "fooView";
}
Let's say the client uses Expression language to render foo and bar; but we use JavaScript to render barOptions.
<html>
<script>
var options = <mytag:toJSON object="${barOptions}"/>;
$("#options").renderOptions( options );
</script>
<body>
<mytag:renderFoo foo="${foo}"/>
<mytag:renderBar foo="${bar}"/>
<ul id="options"></ul>
</body>
</html>
Common conventions tells me this is bad. But the essence of MVC, where the controller sends data and the view determines how to use it, tells me this is good. Is there a better way to do the same thing? Is there any reason why this isn't commonly done? I could request the JSON using a separate call, but then I have to make more requests for the page to load, and there may be logic to determine barOptions in the controller method getFoo() based on other input at the time of the page load.
At first glance I can not say that I see anything blatantly wrong with approach. The only aspect that initially took me off guard was your need to convert data in the model object to json.
For me, JSON usually implies that there is some sort of server side object that needs to be converted so that a client side javascript can access or manipulate its structure in a javascript way. I guess without knowing more of the purpose of the options list, I can't see a reason why json serialization is required here.
By using a Tag to convert a model object to JSON, we avoid an
additional request made by the client
But if we assume that JSON is a requirement (perhaps for some third party jquery plugin), then I absolutely do not see anything wrong with approach.
What is special or different about the barOptions unordered list, why does it have be rendered with json? Why not just use a for loop to build the list items? Or you can have a custom tag that builds out the ul entirely.
Aside from that, I missing the point as how one may perceive this as being bad code.
Normally JSON is requested by JavaScript with an Ajax call, but if in your case it's available at page rendering time, I see nothing wrong with your solution. It's clean, compact code and easy to read. Looks perfectly OK to me, the alternative would be to loop on the options array with a forEach, but this approach looks better.

What are benefits of serving static HTML and generating content with AJAX/JSON?

https://urbantastic-blog.tumblr.com/post/81336210/tech-tuesday-the-fiddly-bits/amp
Heath from Urbantastic writes about his HTML generation system:
All the HTML in Urbantastic is completely static. All dynamic data is sent via AJAX in JSON format and then combined with the HTML using Javascript. Put another way, the server software for Urbantastic produces and consumes JSON exclusively. HTML, CSS, Javascript, and images are all sent via a different service (a vanilla Nginx server).
I think this is an interesting model as it separates presentation from data physically. I am not an expert in architecture but it seems like there would be a jump in efficiency and stability.
However, the following concerns me:
[subjective] Clojure is extremely powerful; Javascript is not. Writing all the content generation on a language created for another goals will create some pain (imagine writing Javascript-type code in CSS). Unless he has a macro-system for generating Javascript, Heath is probably up to constant switching between JavaScript and Clojure. He'll also have a lot of JS code; probably a lot more than Clojure. That might not be good in terms of power, rapid development, succinctness and all the things we are looking at when switching to LISP-based langauges.
[performance] I am not sure on this but rendering everything on user's machine might lag.
[accessibility] If you have JS disabled you can't use site at all.
[accessibility#2] i suspect that a lot of dynamic data filling with JavaScript will create cross-browser issues.
Can anyone comment? I'd be interested in reading your opinions on this type of architecture.
References:
Link to discussion on HN.
Link to discussion on /r/programming.
"All the HTML in Urbantastic is completely static. All dynamic data is sent via AJAX in JSON format and then combined with the HTML using Javascript."
I think that's the standard model of an RIA. The emphasis word seems to be 'All' here. Cause in many websites a lot of the dynamic content is still not obtained through Ajax, only key features are.
I don't think the rendering issues would be a major bottleneck if you don't have a huge webpage with a lot of elements.
JS accessibility is indeed a problem. But then, users who want to experience AJAX must have JS enabled. Have you done a survey on how many of YOUR users don't have it enabled?
The advantage is, you can serve 99% (by weight) of the content through CDN (like Akamai) or even put it on external storage (eg. S3). Serving only the JSON it's almost impossible for a site to get slashdoted.
When AJAX began to hit it big, late 2005 I wrote a client-side template engine and basically turned my blogger template into a fully fledged AJAX experience.
The thing is, that template stuff, it was really easy to implement and it eliminated a lot of the grunt work.
Here's how it's was done.
<div id="blogger-post-template">
<h1><span id="blogger-post-header"/></h1>
<p><span id="blogger-post-body"/><p>
<div>
And then in JavaScript:
var response = // <- AJAX response
var container = document.getElementById("blogger-post-template");
if (!template) { // template context
template = container.cloneNode(true); // deep clone
}
// clear container
while(container.firstChild)
container.removeChild(template.firstChild);
container.appendChild(instantiate(template, response));
The instantiate function makes a deep clone of the template then searches the clone for identifiers to replace with data found in the response. The end result is a populated DOM tree which was originally defined in HTML. If I had more than one result I just looped through the above code.

Categories

Resources