How does the following `src='${loadingGif}'` work inside angular component - javascript

I'm reading the book ng-book on angular 2 and there is the following:
let loadingGif: string = ((<any>window).__karma__) ? '' : require('images/loading.gif');
#Component({
selector: 'youtube-search',
template: `
<div class='container'>
<div class="page-header">
<h1>YouTube Search
<img
style="float: right;"
*ngIf="loading"
src='${loadingGif}' />
</h1>
</div>
I'm interested in this part:
src='${loadingGif}'
The short note in the book says the following:
Notice that our img has a src of ${loadingGif} - that loadingGif
variable came from a require statement earlier in the program. Here
we’re taking advantage of webpack’s image loading feature. If you want
to learn more about how this works, take a look at the webpack config
in the sample code for this chapter or checkout
image-webpack-loader⁴².
But there are no details. Can somebody please how does it all work?

This only works with inline templates (template in *.ts file) but not when the template is in an *.html file (like templateUrl: './my.component.html).
src='${loadingGif}'
Is TypeScript string interpolation and not related to Angular. It replaces ${loadingGif} with the content of loadingGif

Related

Vue templates debugging

Maybe its just the fact that I'm not used to using them, but it's hard for me to read and debug templates. I’m trying to figure out if there is a way to use JSX outside of render method or a good linter that would look inside the templates, but can't seem to find anything.
example of the simple issue where closing tag of is missing inside a template:
template:
<div id="movie-filter">
<h2>Filter results</h2>
<div class="filter-group">
<check-filter
v-for="ganre in ganres"
v-bind:title="ganre"
v-on:check-filter="checkFilter"
<!-- forgot to close the tag with ">" -->
</check-filter>
</div>
</div>
Thanks, any recomendations apreciated!

How to load dynamic HTML into DIV with component? Angular5

I have been trying to find the solution of this problem from two days. Unfortunately, I can not get what I want. I am using Angular5.
<div class="form-group col-md-12" [innerHTML]="GetItemsOfHolder(item.children[1],1,
'UserConfigGroupsLabelHolder') | keepHtml"></div>
This is what my function looks like:
GetItemsOfHolder(item: any,divName:string, recursive: boolean = false,typeName:string="")
{
return html;
}
Everything works fine, unless The html which I am returning contains one package named Select2
This is what I use to add the html into this div it works very fine. Until I wanted to add the dynamic package.
What I mean is return html contains the package component like this:
itemhtml +="<select2 data-type='"+holderItem.itemType+"'
[data]='this.dropdownData."+holderItem.name+"'></select2>"
This just returns the plain text to the browser and doesn't work as expected.
What I want is the string to be turned into component or any other way which works and generates the select2 dropdown.
I have been trying to search so many things.But it doesn't works
This is good but I can not understand this And dynamiccomponentloading is deprecated.
Can anyone please give me an idea How can I resolve this problem? Any example would be a great.
As commented by #Devcon
Angular will sanitize pretty much everything so that is why you are
getting plain text. What you want to look into is ReflectiveInjector
and mainly ComponentFactoryResolver. The main idea is that components
need some other info(services, other components, etc) to be rendered,
so you use the Injector to get Dependency Injection refs then the
Component factory builds your component. You then insert this to a
ViewChild reference. There is a more complicated way of dynamically
making components that uses the compiler and requires a
ModuleWithComponentFactories, this is what angular actually uses.
And searching on the angular, I accept that angular should not be done this way.
As I have to create the fully dynamic page which must be rendered in html. I changed my json little bit and using the
ng-container and ng-template and using ngswitch
I made recursive call in the template it self and found its working very fine.
I get many advantages using this:
The HTML (I render dynamically) itself is in HTML, Code is clean and readable, easily maitainable.
The example given here is pretty much the same I have done.
https://stackoverflow.com/a/40530244/2630817
A small example is here:
<ng-template #itemsList let-itemsList>
<div *ngFor="let item of itemsList;let i = index">
<div [ngSwitch]="item.itemType">
<div class="form-group" *ngSwitchCase="'TEXT'">
<label>
{{item.label}}
</label>
<input id="{{item.name}}" value="{{item.value}}" type='text' class='form-control txtbox ui-autocomplete-input'/>
</div>
<div class="form-group" *ngSwitchCase="'PASSWORD'">
<label>
{{item.label}}
</label>
<input id="{{item.name}}" value="{{item.value}}" type='password' class='form-control txtbox ui-autocomplete-input'/>
</div>
<div class="form-group" *ngSwitchCase="'BOOLEAN'">
<label style='width:40%'>{{item.label}}</label>
<div class="form-group"><input id="{{item.name}}" type='checkbox' /></div>
</div>
<div class="form-group" *ngSwitchCase="'LABEL'">
<label class="form-control">{{item.label}}</label>
</div>
<div class="form-group" *ngSwitchDefault>
<label>
{{item.label}}
</label>
<select2 class="form-control" [data]="GetDropDowndata(item.holderId)" [cssImport]="false" [width]="300" [options]="GetOptions(item.type)"></select2>
</div>
</div>
</div>
You can load every you want in one div, you have to play with ng-template and ng-content.
First you have to create one directive:
import {Directive, ViewContainerRef} from '#angular/core';
#Directive({
selector: '[dynamic]',
exportAs: 'dynamicdirective'
})
export class DynamicDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
After you have to put it in some ng-template like:
<p>
page works!
</p>
<ng-template #sider=dynamicdirective dynamic></ng-template>
and use it like
import {Component, ComponentFactoryResolver, OnInit, ViewChild} from '#angular/core';
#Component({
selector: 'app-page',
templateUrl: './page.component.html',
styleUrls: ['./page.component.css']
})
export class PageComponent implements OnInit {
#ViewChild('sider')
sider;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
}
ngOnInit() {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(SomeComponent);
this.sider.viewContainerRef.createComponent(componentFactory);
});
}
}
and normally will see you component loaded at the place of you ng-template (you can call https://angular.io/api/core/ViewContainerRef#clear if you want to reset your view)
I already play with this, you can find some code here https://github.com/nicearma/dynamic
I thought to leave this here for anyone who encounters the same issue in the future.
If you don't want to bother manually instantiating components with ComponentFactory as the other answers suggest, you can also use a library I wrote for the explicit purpose of loading components into dynamic content: ngx-dynamic-hooks.
You can give it any string that contains the selector of a desired component and it will automatically be loaded in its place. You can even load components by other text patterns other than just their selectors! See it in action in this Stackblitz.
There's a lot more bells and whistles, if you need them. In the link above, you'll find a fairly detailed documentation that should set you up easily.

Nested components elements

I'm stuck on a template/component problem and I couldn't find any answer.
I'm trying to move a plain Javascript project to Angular2. In my project, I actually create some elements by inherit from others.
Example:
File header.html
<header class="some_class"></header>
File header_base.html inherits from header.html
<header> <!-- This is the header element from the header.html file. -->
<img class="some_class" src="path/to/my/image">
...
</header>
EDIT:
To clarify how I actually do, to 'inherits file from another', I use Javascript.
My problem is that I can't find out how to do that in Angular.
My question is, is there any way to accomplish something like that or do I need to change my way of 'templating' things ?
Thanks by advance.
Your question is a little confusing. Can you provide more detail about what the end result should be?
It sounds like what you are looking for is shadow dom insertion point where you have a component that you can put content into. Where you have a component called Header that has some markup and styles applied, but then you can use it in different places with different content?
If so, here is how you would do it (Note: this is Typescript but could be done in plain Javascript. Check the Angular docs for examples):
CustomHeader.ts:
#Component({
selector: 'custom-header',
template: '<header class="some-class"><ng-content></ng-content></header>'
})
export class CustomHeader {
//if you need any logic in that component
}
Then in whatever component you need to use this component, you would import it:
app.ts:
import {CustomHeader} from './CustomHeader';
#Component({
selector: "my-app",
directives: [CustomHeader],
template: `<div>
<custom-header>
<img class="some_class" src="path/to/my/image" />
</custom-header>
</div>`
})
The result is that when you use the component in your html, its content will get wrapped by the contents of the CustomHeader's template. Not sure if that is exactly what your need was though.
EDIT: Here's a good article describing this type of component: http://blog.thoughtram.io/angular/2015/03/27/building-a-zippy-component-in-angular-2.html

Are'nt we Allowed to write html codes if we use backbone.js?

I am learning backbone.js and I have seen some examples like this one.Here the user has not written much html codes inside the editor.html.Only 4 lines of code.But for colour change,size change etc he has done inside editor.js
Please help me understand what all codes we need to keep inside .html file
<div id="page" style="width:2000px;height:2000px;">
<button id="new-rectangle">New Rectangle</button>
<button id="new-circle">New Circle</button>
</div>
You should aim to put all your html in .html file(s). As an app grows, it will help you to keep them separate. The example you link to is a 'simplified' version - this is not how you would structure things in an actual app. You would load html from templates in the render function. A (though this is also simplified as I am relying on script tags) pattern would be:
HTML file:
[...SOME HTML...]
<script type="text/html" id="template-contact">
<div class='contact'>
<h1>Here's my template code</h1>
<strong>name</strong>
<span>email</span>
</div>
</script>
Then in your Backbone view render function:
render: function() {
template: _template($('#template-contract').html(),
this.$el.html(this.template());
return this;
}
Then somewhere else in your Backbone code you create a new instance of the view and render it.
var example = new view_name();
example.render(); //This loads the html template
If you need to dynamically load the html from a server, you can use underscore (or whichever template engine you are using) tags in your template '<%>' and use models. This is best explained in Addy Osmani's book Developing Backbone.js Applications which, incredibly, is free. Here's the link to the relevant section
Whatever you wants to display on the browser you can keep it in .html file and logic to update the dom on run time should be in .js file.

How to include HBS template in Jasmine?

I am building a client-side web application in javascript. To build the templates I have used HandleBars.js templates, i.e. .hbs files.
I am using Jasmine framework for writing the specs for the JavaScript Code.
But I am stuck on loading the .hbs templates from the source files in the specs.
Using the Jasmine-Jquery (Link) plugin I have included the static html templates.
This is part of a sample template :
<li>
<div class="fixedText">
<div class="middleItem">Name</div>
<div class="midItemValue" style = "margin-right: 0.6rem;">
<input id = "textNewGroupName" type="text" style = "width : 300px;" maxlength="300" name="name" value="{{name}}">
</div>
</div>
</li>
included in the hbs file. Because of the similar dynamic values (here name) in the templates I am unable to use the static fixture method.
I found below example by the link that I given in the question, and that fixture is used for HTML
loadFixtures('myfixture.html');
// Run test
some.methodToTest();
// Expect that the methodToTest has modified the content in the div
expect($('#fixtureId')).to...;
I found the answer for HBS also, and it is as follows:-
Instead of loading myfixture.html, I loaded my HBS file.
Moreover the same can be done by var t = readFixtures('myFixture.hbs').
Another way be to use Handlebars.compile('myFixture.hbs')

Categories

Resources