AngularJS 2.0 binding & event handling - angularjs

I am playing around with AngularJS 2.0
My very simple scenario consists of a select box that is bound to a property of component attribute, like this:
<select [(ngModel)]="zeitraum" [value]="zeitraum" (change)="calculate()">
<option>....</option>
</select>
The component class looks like this:
export class MyComponent
{
constructor
(
public zeitraum: number = 10,
public result: number = 0
)
{
}
public calculate()
{
this.result = this.zeitraum * 5;
}
}
So, I have a select box with a couple of options and I want the following behaviour: when a new option is selected, call the calculate() method which simply multiplies 'zeitraum' by 5 and then sets the value of 'result' which is then displayed on the page.
<h1>Result: {{result}}</h1>
The problem is as follows: The calculate method is called but it uses the OLD value of 'zeitraum' (that is, the value before a new option was selected).
I wonder which event to use here. I tried a workaround by using (mouseleave) and (mousemove) events and that seemed to work but it's a really dirty hack so there should be a more elegant solution.
Either I am using the wrong event or I got something else wrong with my Angular code.
Has anybody a suggestion? Thanks a lot in advance.

You should be able to do it like this:
<select [(ngModel)]="zeitraum" (change)="calculate($event.target.value)">
<option>....</option>
</select>
public calculate(zeitraum)
{
this.result = zeitraum * 5;
}

Related

how to customize default view for linkItemCollection in EPiServer

I'm using EPiServer version 11 and I have requirement that when property of type linkItemCollection is rendered using PropertyFor() method, I need to add some custom attribute ( based on condition if target is blank ) to generated hyperlink.
#Html.PropertyFor(x => x.Layout.LinksCollection)
I have idea of creating a custom view under DisplayTemplates in view and adding new view. My query is how can i get default template for linkItemCollection to get it started ?
The easy option would be to o it yourself and not worry about the Property for, the only slight issue is that you may not get inline editing to work.
https://www.jondjones.com/learn-episerver-cms/episerver-developers-tutorials/episerver-properties/how-to-display-a-list-of-links-in-episerver/
To go with your route
[UIHint("MyView")]
[Display(
GroupName = SystemTabNames.Settings,
Order = 100)]
public virtual LinkItemCollection MyProperty{ get; set; }
In Views/Shared/DisplayTemplates add a template MyView.cshtml
Instead of using the PropertyFor you could take full control of the rending yourself.
// FullRefreshPropertiesMetaData asks on-page edit to reload the page
// to run the following custom rendering again after the value has changed.
#Html.FullRefreshPropertiesMetaData(new []{ "RelatedContentLinks" })
// EditAttributes enables on page-edit when you have custom rendering.
<p #Html.EditAttributes(m => m.CurrentPage.RelatedContentLinks) >
#if (Model.CurrentPage.RelatedContentLinks != null)
{
<span>See also:</span>
foreach (LinkItem item in Model.CurrentPage.RelatedContentLinks)
{
#item.Text }
}
</p>
Taken from the EPi documentation
Thanks for your input on this.
I managed to resolve this as below.
public static MvcHtmlString LinkItemCollectionFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
MvcHtmlString result = PropertyExtensions.PropertyFor(html, expression);
return MvcHtmlString.Create(result.ToString().Replace("target=\"_blank\"", "target=\"_blank\" rel=\"noopener noreferrer\""));
}
Hope, it helps someone.

Invoking cells directly from the controller

I am working with cakephp 3.1.7 and figuring out how to invoke view cells or retrieve cell data from the controller. I implemented basic cells with the help of cakephp docs and also http://josediazgonzalez.com/2014/03/20/view-cells/ document which is working fine. However, when I try to return cells directly from the controller I get the following error.
Error: Call to undefined method App\Controller\ProductsController::decorate()
This is what I have:
use Cake\View\Cell;
use Cake\ORM\TableRegistry;
class ProductupdateCell extends Cell
{
public function display($options = []){
if (!empty($options['displaylist'])) {
$this->set('productlist', $options['displaylist']);
return $this;
}else{
$category = $this->request->query['category'];
$this->loadModel('Products');
$query = $this->Products-> find()
-> where(['Products.category' => $category])
-> hydrate(false);
$productlist = $query->toArray();
$this->set('productlist',$productlist);
return $this;
}
}
}
In my controller,
<?php
class ProductsController extends Controller
{
use CellTrait;
public function view($id)
{
$products = $this->Products->findById($id);
$this->set('displaylist', $this->decorate('ProductupdateCell', $products));
}
}
Please correct me where I am going wrong. Is it efficient to use this to update my product list based on user input with ajax request? Can I selectively update the particular cell rendered in my view page? Is there any other method to update the cell directly. Please forgive me if this is a dumb question.
I am working with cakephp 3.1.7 and figuring out how to invoke view cells or retrieve cell data from the controller.
This is an architecturally wrong. They're supposed to be used from the view level.
If you want to have modular and abstracted controller logic either use the CRUD plugin. Or simply go for components. Components are packages of logic that are shared between controllers.
Error: Call to undefined method App\Controller\ProductsController::decorate()
There is no such method in the Controller, CellTrait nor the View class. I don't know from where you got that code, it's also not in the documentation of the cells.

How to show computed property values in EPiServer 8?

In page edit mode I want to show a read-only text that is based on a page property value. The text could for example be "A content review reminder email will be sent 2015-10-10", where the date is based on the page published date + six months (a value that will be configurable and therefore can change anytime). So far I've tried to accomplish something like this by adding another property on the page.
I've added the property CurrentReviewReminderDate to an InformationPage class we use. In page edit mode the property name is shown, but it doesn't have a value. How do I do to show the value in page edit mode (preferably as a label)?
[CultureSpecific]
[Display(
Name = "Review reminder date",
Description = "On this date a reminder will be sent to the selected mail to remember to verify page content",
Order = 110)]
[Editable(false)]
public virtual string CurrentReviewReminderDate
{
get
{
var daysUntilFirstLevelReminder =
int.Parse(WebConfigurationManager.AppSettings["PageReviewReminder_DaysUntilFirstLevelReminder"]);
if (CheckPublishedStatus(PagePublishedStatus.Published))
{
return StartPublish.AddDays(daysUntilFirstLevelReminder).ToString();
}
return "";
}
set
{
this.SetPropertyValue(p => p.CurrentReviewReminderDate, value);
}
}
EPiServer internally uses the GetPropertyValue method (i.e. the opposite of SetPropertyValue) when retrieving content for the UI.
This makes sense, otherwise your "made-up" value would be stored as the real value whenever the content is saved. This would make fall-back values etc impossible to implement.
So, this is by-design (and quite wisely so) in EPiServer. :)
However, you can customize how properties work by:
Using custom editors by applying UI hints
Modifying property metadata (for example, to display a generated value as a watermark in a textbox without interfering with the actual value being saved)
I could be misunderstanding what you're trying to do, but off the top of my head it looks like a custom editor could be a viable option for your use case?
Another solution would be to hook into the LoadedPage-event and add the value from there. This might not be the best way performance-wise since you need to do a CreateWritableClone, but depending on the site it might not matter.
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class EventInitialization : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += eventRegistry_LoadedContent;
}
void eventRegistry_LoadedContent(object sender, ContentEventArgs e)
{
var p = e.Content as EventPage;
if (p != null)
{
p = p.CreateWritableClone() as EventPage;
p.EventDate = p.StartPublish.AddDays(10);
e.Content = p;
}
}
}

Generic EventAggregator?

We want to fire Events, with event names saved in SQL Server
In the SQL Server you'll find ApplicationExitRequestEvent
When we click the menu button, we'll get the string from the MenuItem
Type t = Type.GetType(SelectedMenu.View + "," + "AssemblyName");
var obj = Activator.CreateInstance(t);
if (t != null)
{
//Working firing Event with className
EventAggregator.GetEvent<ApplicationExitRequestEvent>().Publish(null);
//Generic?
EventAggregator.GetEvent<???>().Publish(null);
}
Ist it possible to do?
Working with PRISM and MVVM - WPF - .NET 4.0
if you look at the EventAggregator class, you'll see it's nothing more than a container Dictionary<Type, EventBase> and the GetEvent method. That's it, all the actual work is done in EventBase. In order to achieve what you want, you could modify the class (or make a copy and modify that), and add a method GetEvent( string typeString ) in which you convert the typeString to an actual Type (same way as in your code sample) and use that to fetch the event from the dictionary.
Got it, working fine now!
Pimped the Prism Library, to get the event by Type :-)
/// <summary>
/// Gets the single instance of the event managed by this EventAggregator.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
public CompositePresentationEvent<object> GetEvent(Type type)
{
EventBase existingEvent = null;
events.TryGetValue(type, out existingEvent);
if(existingEvent != null)
return (CompositePresentationEvent<object>)existingEvent;
return null;
}
Thank you guys!

Page.GetRoutUrl in a static method

Some background on what I'm doing
I usually like to have my pages return the url needed to access it. So i will normally have a method like so
public partial class ProductDetails : Page
{
public static string GetUrl(Guid productId)
{
return "fully qualified url";
}
}
on my other pages/controls that need to access this page i'll simply set the link as
hl.NavigateUrl = ProductDetails.GetUrl(id);
I'm toying around with the new UrlRouting stuff in 4.0 and ran into something I'm not sure will work. I'm trying to use the Page.GetRouteUrl in my static method, and obviously it's blowing up due to Page not being static.
Does anyone know if it's possible replicate what i'm doing with GetRouteUrl?
thx
You can do something like:
var url = ((Page)HttpContext.Current.Handler).GetRouteUrl(id);
Note: If you called this method from another page, you may not get the desired result if it's relative-specific in some way...but it's as good as you can get with static I believe.
I got GetRouteUrl to work using Nicks suggestion above.
I also found an alternative way to do it w/o using the GetRouteUrl. You are basically generating it manually using GetVirtualPath
public static string GetUrl(int productId)
{
var parameters = new RouteValueDictionary { { "productId", productId } };
var vpd = RouteTable.Routes.GetVirtualPath(null, "product-details", parameters);
return vpd.VirtualPath;
}

Resources