Custom widgets in AngularJS - javascript

I have a list of HTML widgets which are created dynamically from server data like this (Jade):
.area(ng-repeat="widget in widgetsList.widgets")
h3 {{widget.title}}
p {{widget.type}}
span {{widget.data}}
Widgets are not of the same structure and I don't want to show them visually equal because each of them represents its own functionality. The paragraph in the end of the example just puts data json as a string that I obviously need to render as a proper html widget according to its type that looks like 'important-messages-widget' or 'recent-events-widget'.
Angular looks pretty good but lacks of detailed documentation. How should I manage this case?

In Angular there are two built in directives that are really what makes angular soo powerful.
ng-repeat ( which you are already using)
ng-switch
This seems to be most often misunderstood or not understood or something to that effect by most developers. It gives you the power of a switch statement in your normal programming language in html.
http://docs.angularjs.org/api/ng.directive:ngSwitch
The doc's for it should provide you a good starting point. Combining ngSwitch with ng-repeat will give you a very powerful way of representing your view.
<div ng-switch on="widget.type" >
<div ng-switch-when="important-messages-widget">Important Message</div>
<div ng-switch-when="recent-events-widget">Recent Events ---add more html here </div>
</div>
Hope this helps.

Related

A better alternative to ng-switch?

I'm trying to dynamically load a directive template based on a condition, in my case the type attribute from directive scope. The template that is being loaded looks like this:
<div ng-switch="type">
<div ng-switch-when="player" ...></div>
<div ng-switch-when="npc" ...></div>
</div>
After reading some related questions, I have found that there is a way that I can do what ng-switch does, but within the directive itself. I have tried to use vanilla JS switch inside a function that replaced the template string within the directive, but with no success, my guess would be due to the fact that I was using a scope attribute as the switch condition.
Being new to Angular makes finding and understanding solutions to my problem quite difficult, so if I didnt explain my issue with enough clarity, let me know.
Any help is greatly appreciated.

Inserting html or "templates" with quill.js

I'd like to create a html snippet or template for quill.js which will enable me to create a 3 column 1 row grid. ie:
<div class="row">
<div class="col col-4">
column 1
</div>
<div class="col col-4">
column 2
</div>
<div class="col col-4">
column 3
</div>
</div>
I tried to add <div> tags as shown below however it doesn't work and prints the tags out as text.
quill.setContents([
{ insert: '<div>' },
{ insert: 'World!', attributes: { bold: true } },
{ insert: '</div>\n' }
]);
I also read somewhere that quill.js strips out various html tags but I can't find how to allow them in the docs.
Any help on this would be appreciated.
Cheers :)
Note if you attempt to use the list component as an extension you will run in a number of Quill.js issues-- it doesn't actually support blocks within blocks so you will not be able to nest div's and still use features like headings, only inline elements will be possible, and you will not be able to use <br/> tags because they are wrapped in <p></p> blocks (no blocks within blocks) or use the backspace or enter keys-- this solution is severely limited and virtually impossible to extend, nobody has discovered a good workaround, you can't tell that from the issues board because issues related to architecture are systematically deleted... you will find that your delta saving will be off, make sure any extensions you make can actually save using the native format. I find the answer to modify the list element quite misleading as it's so clearly different to the requirements stated here... if you hit return within one of it's container blocks, it'll splice into a new block.... also the embed functionality is not the same anymore, so you will have trouble with that workaround.
My advice is to try another framework like slate.js or prosemirror, they are newer and have their own issues but don't suffer from the same architectural flaws and have nesting with first class data models. You will definitely have better luck with support.
Quill does not let you make arbitrary HTML modifications, as they are error prone and earned the previous generation of rich text editors their notoriety. Parchment is Quill's abstraction that that allows for deep customization and a good resource is: Cloning Medium with Parchment.
You may be able to use dangerouslyPasteHTML for some use cases but that passes through Quill's matchers so the pasted content's HTML may be different from what you pass in.

JS templating engine that preserves elements

I have the following problem:
A have a web application where I regularly need to update the user interface when data changes. The data consists of a list of items with different attributes. Because the UI representations of these items can be complex, I use JS templating to render them. When they change I just replace them in the DOM with the HTML representing their updated state.
This approach is simple but has several problems:
you need to re-attach all event handlers because you practically replace elements
there is a flickering effect when reloading resources (probably can be solved using document fragments)
it's impossible to work with developer tools (inspector) if the content changes frequently because, again, all the elements are replaced
So I was wondering if there is any JS templating engine of that many that can deal with the situation. I'm thinking of a feature that intelligently matches elements of the new render and an old one and only changes the content when it has really changed.
I'm thinking of something like this:
Old HTML
<div>
<h1>TV</h1>
<span>$250</span>
Add to cart
</div>
New HTML
<div>
<h1>TV</h1>
<span>$260</span>
Add to cart
</div>
The templating engine find the <span> in the original DOM and replaces its changed value but leaves the rest of the elements intact.
Finally I came across Rivets.js which a lightweight, highly extensible JavaScript templating engine with real time data binding. I love it so far, it's exactly what I needed.
you can try the AngularJS
A simple example:http://jsbin.com/opayuf/4/edit
you can check out these examples if they can meet your requirements
http://tutorialzine.com/2013/08/learn-angularjs-5-examples/
HandleBarsJs may be the one you need, you could see the discussion on
Handlebars.js: Use a partial like it was a normal, full template
You can also try Ember js based on HandlerBarsJs, you can check is out
http://emberjs.com/guides/templates/handlebars-basics/
http://emberjs.com/guides/templates/rendering-with-helpers/

Advantages Of Putting HTML in Javascript

I am wondering if it is better to put your html in javascript or in your html files.
For example having my js file have this
$('<div>').addClass('test').append(
$('<p>').text('test1'),
$('<span>').text('test2'),
$('<span>').text('test3')
).insertAfter( $('#test1') );
VS
My html file looking like this
<div id="#test1"></div>
<div class="test">
<p>test1</p>
<span>test2</span>
<span>test3</span>
</div>
and the js file have:
$('.test').show();
Highly subjective and depends on contexts of course.
In a web page, most of the content is already known. No reason not to just put the content in the HTML and use CSS (and maybe Javascript when really needed) to style in.
In a web application, however, things are not so well known. The document is much more dynamic and using Javascript to add/remove elements is required.
BTW, your two pieces of code do two different things. In the first example you give it a class of test and in the second you are giving it an ID of #test1. This is an invalid ID and should be test1. The selector for that ID would be #test1 which may be causing some of the confusion.
This is probably okay for just straight-up webpages, but for web applications you should really look into a templating system such as mustache.js(https://github.com/janl/mustache.js) or Handlebars.js(http://handlebarsjs.com/).
That way, you can keep your HTML in external template files and use Javascript objects and arrays to fill them with data. For example, a mustache template might look like:
<div id="{{id}}"></div>
<div class="{{class}}">
<p>{{name}}</p>
<span>{{prop1}}</span>
<span>{{prop2}}</span>
</div>
And you would have an object that looks like this to fill it:
var obj = {
id: "myID",
class: "some classes",
name: "Martin Brennan",
prop1: "whatever",
prop2: 22
}
And you would use the template with the object like this (after loading the template into a variable):
Mustache.render(template, obj)
Like Jeremy J Starcher said though, this is highly subjective, and I would suggested that you give templating systems a try to see if you can see the value in using them in your project(s).
Of course the second option is much better and faster.
If you use
$('<div>').addClass('test').append(
$('<p>').text('test1'),
$('<span>').text('test2'),
$('<span>').text('test3')
).insertAfter( $('#test1') );
browser must parse JavaScript. And each time you use $() you are creating an object which has a lot of properties and methods which you don't use (useless!). And of course the browser must parse the HTML too.
But if you use
<div id="#test1"></div>
<div class="test">
<p>test1</p>
<span>test2</span>
<span>test3</span>
</div>
browser only has to parse HTML and it's much faster.
One of the largest benefits of using the 2nd, hard-coded HTML method is that it'll still show up for people with JavaScript disabled. It's hard to verify exactly how many users don't have JS enabled (because most trackers use JS..) but last guesstimate I heard was somewhere around 5% of internet users.
Moral of the story - make your site work without JavaScript. Then and only then add JavaScript to make it look prettier/ add additional (non essential) features.
The simple answer is that static content should be created using normal markup, while Javascript should be used for dynamic content.
Also, in many cases you can use both. You can have static HTML markup with style="display:none", and then use Javascript to change the style to make it appear and disappear as needed.

JavaScript framework for building out a dynamic but server-side driven frontend

I am looking at building a small app that is more or less several nested lists, and selecting various items in each list will filter the contents of the other nested lists.
List One
Apple
Phone
iPhone
Computer
Macbook Air
Samsung
Phone
Galaxy S
List Two
Best Buy
Ann Arbor, MI
Chicago, IL
Walmart
Lansing, MI
If a user Clicks on "Apple > Phone", the server will find the associated entiries in list Two for, and update List Two to show only "Best Buy" (assuming Best Buy is the only store selling Phones made by Apple)
My question, is does anyone have a recommendation for what Front end JS library I should use to build this out? This is going to be alot of updating the DOM (the lists) based on AJAX JSON responses from the server.
I took a look at KnockoutJS but things seemed to get messy trying to create a viewModel for each list, and updating it via the KnockoutJS mappings library.
I was thinking about simply using jQuery but Im not a huge fan of building out large sections of the DOM with it (it seems to get ugly quickly).
One thing I would like to avoid (and why I was looking at KnockoutJS) is I dont like writing markup in code. I like the idea of maintaining my Markup in the "HTML", and "binding" the JS data to these elements through a framework.
Also, I hope to use jQuery for all the visual "fluff", event binding, etc.
Thanks
I ended up settling on Backbone.js [1]
It seems a bit more flexible than Knockout.js in terms of the bindings. I am using Backbone supported JS Templates for building out each list level. This has required a bit of code, but Backbone is very flexible (thus the bit of code). Im sure this is possible in many other JS frameworks, but I think i've been able to make more progress w Backbone is I dont need a deep understanding of the framework/API/intricacies to make it work - the(my) code may be more verbose, but because of this its easier to piece together how everything works.
[1] http://backbonejs.org/
This is more of a partial answer, trying to tackle the concept of "maintaining...Markup in the 'HTML'". I would create a generic menu item in the HTML that can be the template for each menu item, like so:
<li id="menuItemTemplate" class="menuItem">
<span class="menuItemText"></span>
<ul class="submenu"></ul>
</li>
This would not be in a visible place on your page; it would simply be the HTML that gets inserted for each menu item. Then, when you go to add menu items, your JavaScript would be in charge of adding as many menuItem elements as you needed in your list. As far as HTML manipulation, JavaScript would only need to do things like add id or class attributes to organize or style your data, as well as add the text content of each item. A sample implementation might look like this (I love jQuery):
function loadMenuItem(text, parentId) {
// Grab the template
var newItemHtml = $("#menuItemTemplate")[0];
// Set its id to something unique
$(newItemHtml).attr("id", getNextId());
// Set the text
$(newItemHtml).find("span.menuItemText").html(text);
// Put it in the clicked menu
$(parentId + "ul.submenu").append( newItemHtml );
}
In the end, I won't be programming your project, though. I can only give you my preference. If this is going to take a good amount of time, I'd say that the best thing for you to do is to try out all of the frameworks that sound interesting (on a small scale, obviously) to get a general feeling for how you like developing DOM-transforming apps in each one. That'll give you a better idea of which you'll like more as well as introduce you to different frameworks.
Not a direct answer to the question - still it is worth to take a look at Kendo UI MVVM
MVVM using Kendo UI in three simple steps
Kendo UI Web MVVM
Understanding MVVM – A Guide For JavaScript Developers
MVVM in Kendo UI Walkthrough
Build Single Page Apps – Part 7 – MVVM and KnockoutJS

Categories