How can I embed a twitter timeline in a Durandal view? - durandal

The code to embed the widget is nice and simple, but it includes javascript in tags.
Durandal appears to strip out such script tags.
How do I use the embed code in a Durandal view?
https://dev.twitter.com/web/embedded-timelines
<a class="twitter-timeline" href="https://twitter.com/XXX" data-widget-id="XXX">Tweets by #XXX</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

You would need to write a custom Knockout binding, or create a Durandal widget where the view is your tag, and the viewModel handles the JavaScript in your tag.
Some notes: In your widget's view model, you would avoid d.getElementsByTagName(s) in favor of simply referencing the view reference passed in to either the attached or compositionComplete handler that Durandal provides. In fact, you could pretty much eschew all direct DOM manipulation in favor of Durandal's imported view references and Knockout's/Durandal's templating/composition.
UPDATE
Take a look at this from the documentation you reference: "If you’re already including our ‘widgets.js’ JavaScript in your page to show embedded Tweets or Twitter buttons, you don’t need to include this script again; it updates automatically to support new features."
This could lead you down the path of simply referencing widgets.js in a script tag in your index.html or index.chtml file.
You cannot use script tags in Durandal views, but you can use them in your index page.
SECOND UPDATE
Once widget.js has been referenced in a script tag in the index.html or index.chtml (or perhaps even by using AMD), it becomes a matter of choosing the proper Durandal point at which to load the Twitter widget. This could be either in the attached handler or in the compositionComplete handler, as indicated above.
As the OP pointed out in his comments, a functional place to do this is compositionComplete, in the following manner:
var compositionComplete = function () {
twttr.widgets.load();
}
as documented here.
This assumes that twttr is either on the window or injected into the viewModel.
POSSIBLE MEMORY LEAK
It is equally important to note that unloading of widgets must take place in the Durandal's detached handler. Use Twitter's API to unload, and then be sure to nullify the windows reference.

Related

What is the difference between <router-link> and $router.push?

<router-link> in my opinion takes more work to implement, since you can add $router.push to any element with an #click event.
What are the pros and cons of each approach? Is there any instance, where <router-link> can not be replaced by $router.push?
While router-link's handler does the same $router.push(), it also performs under the hood a handful of useful actions that you will have to implement by yourself to assure the navigation works as expected in every scenario. For example, it activates a "navigation guard" to check for the validity of the triggering event, catches any navigation errors, also, it is the implementation of active route detection and styling which may be a pain to implement in complex navigations (for ex. multilevel navigation menus) that is also simplified by the router-link implementation.
These are some of the pros that I could spot at a first glance at its source code. You can look at it for a more in depth comparison here
First of all is a tag like a tag in HTML so you can not use it inside your script tags. You can only use it inside tags. You have to give to attribute to router-link and you do not need to use click etc.
However, for bigger projects sometimes you need to redirect to another page after you submit a form, or anywhere you like to use redirection in your js. That's why there is $router.push, the $router object is vue-router object so you have all functions that vue-router serves you.

Aurelia - dynamically create custom element in a view-model

I have an Aurelia app where a user can click on a button and create a new tab. The tab and its content (a custom element) do not exist on the page before the user clicks the button. I am generating the HTML for the content at runtime (via Javascript) in my view model.
I keep seeing mention of using the template engine's compose or enhance functions, but neither are working for me. I don't know how I would use the <compose> element (in my HTML) since I am creating the element based on the user clicking a button.
My thought was that the button has a click.delegate to a function that does ultimately does something like
const customElement = document.createElement('custom-element');
parentElement.appendChild(customElement);
const view = this.templatingEngine.enhance({
element : customElement,
container : this.container, // injected
resources : this.viewResources, // injected
bindingContext: {
attrOne: this.foo,
attrTwo: this.bar,
}
});
view.attached();
But all this does is create an HTML element <custom-element></custom-element> without actually binding any attributes to it.
How can I create a custom element analogous to <custom-element attr-one.bind="foo" attr-two.bind="bar"></custom-element> but via Javascript?
As you pointed out in your own answer, it's the missing resources that caused the issue. One solution is to register it globally. That is not always the desired behavior though, as sometimes you want to lazily load the resources and enhance some lazy piece of HTML. Enhance API accepts an option for the resources that you want to compile the view with. So you can do this:
.enhance({
resources: new ViewResources(myGlobalResources) // alter the view resources here
})
for the view resources, if you want to get it from a particular custom element, you can hook into the created lifecycle and get it, or you can inject the container and retrieve it via container.get(ViewResources)
I found the problem =\ I had to make my custom element a global resource.

Initialize dynamic Component in Code using Vue.js

I am currently developing a web application that is used to display elements for events on a map provided by HERE Maps. I am using Vue.
I have some components, but the relevant component is the component HereMaps.vue which initializes the map using the HERE Maps Api.
The HERE Maps Api provides the possibility to place so called InfoBubbles on the map showing additional information. These InfoBubbles can be provided some HTML-code in order to customize their appearance.
Please refer to the documentation for additional information
Following the documentation the code looks something like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<div class='someClass'>Some Content</div>"
});
this.ui.addBubble(bubble)
This is happening after mount in the "mounted" method from Vue in the "HereMaps" component.
The Bubbles are added in a "closed" (hidden) form and dynamically "opened" to reveal their content when the corresponding marker icon on the map is clicked. Therefore the HTML-code is present on the DOM after the component is mounted and is not removed at a later stage.
Now instead of supplying custom code within each bubble added to the UI i want to just add a component like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<myDynamicComponent></myDynamicComponent>"
});
this.ui.addBubble(bubble)
It does not matter to me wether the component is initialized using props or if it is conditionally rendered depending on the state of a global variable. I just want to be able to use the "myDynamicComponent" in order to customize the appearance in a different file. Otherwise the design process gets very messy.
As far as i know this is not possible or at least i was not able to get it work. This is probably due to the fact that the "myDynamicComponent" is not used within the "template" of the "HereMaps" component und thus Vue does not know that it needs to render something here after the directive is added to the DOM in the "mounted" method.
This is what the InfoBubble looks using normal HTML as an argument:
This is what the InfoBubble looks using the component as an argument:
It appears to just be empty. No content of the "myDynamicComponent" is shown.
Does anyone have any idea how i could solve this problem.
Thank You.
Answer is a bit complicated and I bet you wouldn't like it:)
content param can accept String or Node value. So you can make new Vue with rendered your component and pass root element as content param.
BTW, Vue does not work as you think, <myDynamicComponent></myDynamicComponent> bindings, etc exists in HTML only in compile time. After that all custom elements(components) are compiled to render functions. So you can't use your components in that way.
Give us fiddle with your problem, so we can provide working example:)

Aurelia popover checkbox checked.bind not reflecting on the view model

We have implemented checkbox in popover. There we are using checked.bind , but in the view model its not reflecting its value on change of the checkboxes.
Sample Gist Run Provided below:
Gist Run
Thanks in Advance
Programmatically injected HTML needs to be compiled manually
The integration with bootstrap I provided to you earlier cannot do this. The bootstrap plugin assigns the innerHTML property of the popover and it does this outside of aurelia's rendering pipeline. The HTML is therefore not compiled by aurelia, which is why bindings (and other aurelia behaviors) will not work.
The templating framework takes care of this for you automatically as long as you are following conventions (such as custom elements). In any other case you'll need to manually work with the ViewCompiler.
In case you're interested, you can see an example with programmatically generated HTML in this gist. Also see this question if you want to know more about it. I do not recommend it in this scenario however.
Use aurelia-dialog
A tooltip (or popover) is just that: a tip on how to use the tool. It should not need more than some plain markup, text and styling (of course this is subjective to some degree, and some people may disagree)
For collecting user input in-between pages or screens, I'd argue a modal dialog is a better fit because of its property to "pop out" more and to de-emphasize the rest of the screen until the user either proceeds or cancels.
More importantly, by using aurelia-dialog your bindings and behaviors will simply work because, well, it's an aurelia plugin :-)

Using TagHelpers vs ViewComponents in ASP.NET MVC6

I'm trying to understand the use case differences between TagHelpers and ViewComponents in asp.net 5 because the end result functionality seems very similar. We have TagHelpers that can create new HTML tags that get parsed by the Razor engine and then ViewComponents that get explicitly invoked. Both return some HTML content, both are backed by their respective base classes, both have async versions of methods they can implement to get their work done.
So when would one be used over another? Or am I missing some information?
There's definitely some conceptual overlap between TagHelpers and ViewComponents. TagHelpers are your utility to work with HTML where ViewComponents are your way to stick to C#, do isolated work and then spit out HTML. I'll go into each in detail:
ViewComponents
Your conceptually equivalent mini-controller; you will see that many of the methods/properties that ViewComponents expose are very familiar to those that exist on a Controller. Now as for invoking ViewComponents, that's more equivalent to utilizing HTML helpers (one thing TagHelpers make better). To sum up ViewComponents: Their primary purpose is to feel like a controller, stay in C# land (there may be no need to add utility to HTML), do smaller/isolated work and then spit out stringified HTML.
TagHelpers
A utility that enables you to work along side existing HTML or create new HTML elements that modify what happens on a page. Unlike ViewComponents TagHelpers can target any existing HTML and modify its behavior; example: you could add a conditional attribute to all HTML elements that would conditionally render the element server side. TagHelpers also allow you to intermingle common HTML terms, ex:
<myTagHelper class="btn">Some Content</myTagHElper>
As you can see we're adding a class attribute to our TagHelper just as if it were HTML. To do this in ViewComponents, you'd need to pass in a dictionary of attributes or something equivalent (unnatural). Lastly multiple TagHelpers can run over a single HTML element; each having their own stage at modifying output (allows entry for modular TagHelper toolkits). To sum TagHelpers up: They can do anything that ViewComponents can do and more BUT do not feel familiar to things like Controllers that ASP.NET developers are used to; also some projects may not want to intermingle server side HTML.
Extra:
I recently did a video showcasing the benefits of TagHelpers. Basically a walk through of what they're good at and how to use them. You can watch it here.
When deciding which one to use I always consider how complex the HTML of the component will be.
If it's something simple like a tree view or a pager
<ul class="jstree">
<li>Node 1</li>
<li>...</li>
</ul>
That is candidate for tag helper, because it's simple. Large HTML in a C# code would be hard to maintain.
On the other hand if it's complex HTML with many divs, images and configuration like a full blown menu where it can be vertical or horizontal that's your view component. Benefit of view component is that you can use multiple views so for menu so you can separate horizontal.cshtml & vertical.cshtml while reusing same backend code.
Turns out that in .Net Core 1.1, you can call a ViewComponent using the tagHelper syntax.
Regarding Taylor's comment "Their primary purpose is to feel like a controller", it is true, but since you cannot directly call this "micro-controller" directly, the "controller-like" behavior is limited in that you can only create a part of a page, you cannot call it again (say via an ajax call, an Edit Action, etc).
One primary difference between TagHelpers and ViewComponents relates to how much work needs to be done by the object. TagHelpers are fairly basic, requiring only a single class that overrides the Process method to produce the output of the TagHelper. The downside is that if you do any complex work to create inner HTML in the TagHelper, it has to all be done in code. In a ViewComponent, you have a mini-controller capable of doing a lot more work, plus it returns a view, where you have actual Razor syntax code that can be mapped to a model.
Another post mentioned that ViewComponents are more "HTML Helper"-y in how you call them. ASP.NET 1.1 addressed that issue, so that you can call it with
<vc:view-component-name param1="value1" param2="value2></vc:view-component-name>
For most purposes, a TagHelper has a definite advantage, because it's easier. But if you need a more robust solution, ViewComponent is the way to go.
And yet something that kind of defeats the purpose of View Components (IMHO) is that from the View Component class there seems to be no way to access the Inner Html of the VC if you use the tag helper syntax:
<vc:MyComponent id="1" att="something">
Some HTML markup you would not want to put in an attribute
</vc:MyComponent>
There are however good applications of a VC such as the Bootstrap Navigation Bar View Component I saw in a TechieJourney blog post.