how can I implement subscribe in html template in angular7 - angular7

getEmployee() is a method in my service page and now I want employee list without subscribe showEmployee() method in my component using HTML template.
showEmployee(){
this.employeeModel= this._empService.getEmployee();
}

employeeModel : Observable<any>
or If It as List
employeeModel : Observable<any[]>=[];
showEmployee(){
this.employeeModel= this._empService.getEmployee();
}
In Html if You have List Type Then
<div *ngFor="let data as employeeModel | async">
.... code for show data Like {{data.property Name }}
</div>
If Its an Object
<div> {{employeeModel | async}}</div>

You need the pipe in the html element:
<p *ngFor="let data as employeeModel | async">
<span> {{data.empName}}</span>
</p>

Related

how to change html view using binding in angular 6

I have an angular 6 project , I have a component for book like this
<div class="col-md-4 agileinfo_single_left">
<img id="BigBookView" src="public/books/images/{{book.photo}}" alt=" " class="img-responsive">
</div>
<div class="col-md-8 agileinfo_single_right">
<h1>{{book.name | uppercase}}</h1>
<h2>Series: {{book.seriesName}}</h2>
<h3>Author: {{book.author}}</h3>
<h4></h4>
<div class="w3agile_description">
<h4>Summary : {{book.summary}}</h4>
</div>
<div class="snipcart-item block">
<div class="snipcart-thumb agileinfo_single_right_snipcart">
<h4 class="m-sing">Price: {{book.price}}$</h4>
<h4 class="m-sing">Seller: {{book.seller}}</h4>
</div>
<div class="snipcart-details agileinfo_single_right_details">
<form action="#" method="post">
<fieldset>
<input type="submit" name="submit" value="Add to cart" class="button">
</fieldset>
</form>
</div>
</div>
all of this is inside a modal and every time I choose a book and the modal is opened and suppose to show the book data in this html.
This is the component type script
export class BigBookViewComponent implements OnInit {
#Input()
public book:Book = new Book();
constructor() { }
ngOnInit() {
}
public changeBook(newBook: Book) {
console.log(this.book);
this.book = newBook;
}
}
using the function changeBook I send to this component a new book to show but the html and the UI don't chagne, even though I can see in the console.log(this.book); line that the book is indeed being sent.
How can I change the html to show a diffrent book?
You should assign the book on ngOnInit method.
When assigning in the constructor the single instance of the component will keep the original book.

Sitefinity Custom Fields for list widgets and how to use them in MVC view templates

I've added a Custom Field to the List Widget in Sitefinity 8.1, it's Type is Related data and it's Data type is Pages. The field name is LinkedPageUrl.
Works perfectly in the back end allowing me to select a page from system and store it against that particular List Item.
I can't find any place in Sitefinity's documentation that explains how I would programmatically use this field in a MVC based List.SimpleList.cshtml view template that I'm customizing.
I've seen this being used in the News widget where there is an associated Image for each News Article:
<img src="#Html.Raw(item.Fields.RelatedImg.Fields.MediaUrl)" class="img-responsive" />
But I don't get close to this because I don't have the slightest idea where to begin... What's the model structure, syntax, etc.
My objective is to change each list item rendered out into an anchor and the anchor should make use of this Related Data field's URL for it's Href property.
EDIT:
You can do something like this in the widget template:
#foreach (var item in Model.Items)
{
<h3 #Html.InlineEditingAttributes(Model.ProviderName, Model.ContentType.FullName, (Guid)item.Fields.Id)
#Html.InlineEditingFieldAttributes("Title", "ShortText")>
#item.Fields.Title
</h3>
<ul>
#foreach (var listItem in ((ListViewModel)item).ListItemViewModel.Items)
{
<li #Html.InlineEditingAttributes(Model.ProviderName, ((ListViewModel)item).ListItemViewModel.ContentType.FullName, (Guid)listItem.Fields.Id)>
<div #Html.InlineEditingFieldAttributes("Title", "ShortText")>
#listItem.Fields.Title
</div>
<div class="sfMultiRelatedItmsWrp">
<h2 class="sfrelatedItmTitle">Related pages</h2>
#foreach (var link in listItem.Fields.LinkedPageUrl)
{
var node = PageManager.GetManager().GetPageNode(link.Fields.Id);
var url = PageExtesnsions.GetFullUrl(node);
<div>#link.Fields.Title - #url</div>
}
</div>
</li>
}
</ul>
}
This is given that you selected that multiple pages can be selected per list item.
EDIT: Make sure to include the following namespaces
#model Telerik.Sitefinity.Frontend.Mvc.Models.ContentListViewModel
#using Telerik.Sitefinity.Frontend.Lists.Mvc.Models;
#using Telerik.Sitefinity.Frontend.Mvc.Helpers;
#using Telerik.Sitefinity.Modules.Pages;
EDIT2: If the custom field allows for only 1 page to be selected then it should look like this:
<div class="#Model.CssClass">
#foreach (var item in Model.Items)
{
<h3 #Html.InlineEditingAttributes(Model.ProviderName, Model.ContentType.FullName, (Guid)item.Fields.Id)
#Html.InlineEditingFieldAttributes("Title", "ShortText")>
#item.Fields.Title
</h3>
<ul>
#foreach (var listItem in ((ListViewModel)item).ListItemViewModel.Items)
{
<li #Html.InlineEditingAttributes(Model.ProviderName, ((ListViewModel)item).ListItemViewModel.ContentType.FullName, (Guid)listItem.Fields.Id)>
<div #Html.InlineEditingFieldAttributes("Title", "ShortText")>
#listItem.Fields.Title
</div>
<div class="sfMultiRelatedItmsWrp">
<h2 class="sfrelatedItmTitle">Related pages</h2>
#{
var node = PageManager.GetManager().GetPageNode(listItem.Fields.LinkedPageUrl.Fields.Id);
var url = PageExtesnsions.GetFullUrl(node);
}
<div>#listItem.Fields.Title - #url</div>
</div>
</li>
}
</ul>
}
A good starting point is this article

Knockout Sending ViewModel as parameter

I am experimenting with Knockout with TypeScript and am trying to send a view model that contains another model as parameters to a function like:
TypeScript:
export interface IEmployee {...}
export interface ICompany {...}
export class ViewModel() {
constructor(company : ICompany) {}
public setAsOwner(parent : ViewModel, person : IEmployee) {
parent.company.updateOwner(person.id);
}
}
// In a different file
ko.applyBindings(new ViewModel(new ICompany()));
HTML:
<ul data-bind="foreach: employees">
<li>
#*Employee details...*#
<button data-bind="click: $root.setAsOwner.bind($parent, $data)">
Set as new owner
</button>
</li>
</ul>
However I keep getting an error saying that parent.company is undefined. What is the right way to pass the view model as a parameter to its own function?
The click binding handler function automatically receives the current employee item as the first parameter, and if you call $parent.setAsOwner from a wrapper function, the parent view model is available to the method via this.
So change the setAsOwner method to:
public setAsOwner(person : IEmployee) {
this.company.updateOwner(person.id);
}
and the HTML to:
<ul data-bind="foreach: employees">
<li>
#*Employee details...*#
<button data-bind="click: function(employee) { $parent.setAsOwner(employee); }">
Set as new owner
</button>
</li>
</ul>

Dart: how to refer to a component element, when there are multiple instances of the component?

I have a template:
<element name="x-my-elem" constructor="MyElem" extends="div">
<template>
<div>
<button on-click="onClick()"> Button </button>
<div id="displayMe">
</div>
</div>
</template>
</element>
And script:
class MyElem {
onClick {
query("#displayMe").innerHtml = "hello";
}
}
Now, there are multiple instances of the component in the html file:
<div is="x-my-elem" id="p1" ></div>
<div is="x-my-elem" id="p2" ></div>
...
I want each button to change only "displayMe" that belong to it. How to achieve it?
Is there a way to generate unique Ids? Something better then this.elements[i] ?
First, I think you should prefer classes to id's for component internals, because you can have multiple instances of the component, as you do here.
Either way, the way to scope your query to the component is to use this.query() instead of query(), like so:
class MyElem {
onClick {
this.query(".displayMe").innerHtml = "hello";
}
}

Use MVC helpers inside jquery.tmpl templates

I have a simple foreach template and inside every element I want an ActionLink but that ActionLink needs to send an Id to edit the element.
The item to be templated:
<div data-bind="template: {
name: 'postsTemplate',
foreach: posts
}">
</div>
The template:
<script id="postsTemplate" type="text/html">
<h2 data-bind="text: Title"></h2>
<p class="post-info">
<p class="post-info" data-bind="text UserName"></p>
<span data-bind="Body"></span>
<p class="post-footer">
#Html.ActionLink("Comments", "IndividualPost", "Post", null, null, "comments", new {id = })
</p>
</p>
</script>
How can I send the actual post Id through the ActionLink? I mean, How I can access to the post's id without using data-bind? (Because it's a helper).
If you would implement your own ActionLink extension along the line of:
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText,
string actionName, string controllerName,
object routeValues, bool noEncode)
{
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var url = urlHelper.Action(actionName, controllerName, routeValues);
if (noEncode) url = Uri.UnescapeDataString(url);
var tagBuilder = new TagBuilder("a");
tagBuilder.MergeAttribute("href", url);
tagBuilder.InnerHtml = linkText;
return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
}
Then you could make your template like:
<p class="post-info">
<p class="post-info" data-bind="text UserName"></p>
<span data-bind="Body"></span>
<p class="post-footer">
#Html.ActionLink("Comments (${CommentCount})", "IndividualPost", "Post",
new {id = "${id}"}, true)
</p>
</p>
the serverside html generated would then look like:
<p class="post-info">
<p class="post-info" data-bind="text UserName"></p>
<span data-bind="Body"></span>
<p class="post-footer">
Comments (${CommentCount})
</p>
</p>
which in turn is a perfect template in my opinion.
The reason for an ActionLink extension is the fact that the normal Html.ActionLink encodes your url to /Post/IndividualPost/%24%7Bid%7D which doesn't work for the template
option 1:
- your posts viewmodel is probably coming from the server, it could contain the link.
{
title:'post title',
commentsUrl:'/Indivdualpost/comments/123'
}
on the server
return new post { comment='post title', commentsUrl=Url.Action('Comments','Individualposts', new {id=1234}); }
and then render the comments url in the template:
<a data-bind="attr: {href:commentsUrl}">comments</a>
option 2:
script using a form
<form id="frm" action="#Url.Action("Comments","IndividualPost")>
<input type="hidden" name="id" id="postid"/>
<!-- template stuff -->
</form>
and in the template
<p class="post-footer">
<a data-bind="click:function(){ $('#postid').val(${$id}); $('#frm').submit(); }">comments</a>
</p>
(the click attribute is quite ugly, should be improved using a binding handler or a viewmodel function ( http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html ))

Resources