Angular 2 routerLink optional route part - angular2-routing

I want to achieve something like this with a relative routerlink:
[routerLink]=[routePart, 'Create']
where routePart is a component property and can be empty, meaning it should be ignored, or have some value
So if current route is '/Products' then if
routePart = '' we want to get '/Products/Create'
routePart = 'xyz' we want to get '/Product/xyz/Create'
But what I find in the first case it becomes an absolute path and resolves to '/Create'
I can get it working using an expression in the binding but this seems kinda ugly
[routerLink]='routePart == '' ? 'Create' : 'xyz/Create''
Is there some clean way to get this working?

Try this.
<a *ngIf="routePart === '' " [routerLink]="Create" />
<a *ngIf="routePart === 'xyz' " [routerLink]="xyz/Create" />

Related

Asp-route-id: passed integer becomes 0

I have the following problem.
I have a product for which I run some tests.
In my cshtml page, I show the test runs for some product item, like this:
<td><a asp-action="TestDetail" asp-route-id="#Model.ResultViewModels[i].TestRunId">Content</a></td>
TestRunId is an integer. For example, TestRunId could be 9. This works: the URL looks correct.
In my cshtml page, the user can click on this, to see more details.
However, when I log the asp-route-id in my controller, this TestRunId seems to be 'lost'. In my example below, the second logging shows testrunId: 0. I expect this to be also 9.
public IActionResult TestPlanRunDetail(int TestRunId)
{
logger.LogInformation("TestPlanRunDetail function called.");
logger.LogInformation("TestRunId: " + TestRunId);
// Omitted for brevity
return View(detail);
}
The parameter name in asp-route-xxx must be same as the parameter name in the backend (int xxx)
So, change one of your param names to match the other
asp-route-{value} is an Anchor Tag Helper.
The Anchor Tag Helper enhances the standard HTML anchor (<a ... ></a>) tag by adding new attributes. By convention, the attribute names are prefixed with asp-. The rendered anchor element's href attribute value is determined by the values of the asp- attributes.
The Reason:
Any value occupying the {value} placeholder is interpreted as a potential route parameter
Therefore, if you use asp-controller="controller" asp-action="action" asp-route-id="#Model.ResultViewModels[i].TestRunId".
The generated HTML href will be href="/controller/action?id=0">Content</a>
where 0 is the actual #Model.ResultViewModels[i].TestRunId.
Notice that the parameter name in href is id instead of TestRunId?
Your TestPlanRunDetail(int TestRunId) take TestRunId, but not id, and that is why you get TestRunId=0.
The Easier Solution:
Change asp-route-id to asp-route-TestRunId (or asp-route-testrunid as it is not case sensitive).
Alternate Solution:
Define a default route template in Startup.Configure:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{action=Index}/{id?}");
});
In the model:
<a asp-action="TestDetail"
asp-route-id="#Model.ResultViewModels[i].TestRunId">
Content
</a>
Then, the generated href will be href="/TestDetail/12".

Include specific attribute or child-element text in breadcrumb rendering

Within the author it displays a breadcrumb, and I know you can modify its display to either some other static text or localisation, but I'm wondering if it's possible to dynamically show an attribute, or execute some other context-specific xpath dynamically.
As a test I can change the breadcrumb using the localisation editor variable ${i18n()}.
cc_config.xml
<elementRenderings platform="webapp">
<render element="num" as="${i18n(test)}" annotation="${i18n(test)}"/>
translation-cc.xml
<key value="test">
<comment></comment>
<val lang="en_US">Year</val>
"Year" is actually a num element.
However, trying any other variable, even 'more static' ones like ${cf} or ${tp} simply render the variable text literally, instead of evaluating it.
cc_config.xml
<elementRenderings platform="webapp">
<render element="paragraph" as="${xpath_eval(./#eId)}" annotation="${xpath_eval(./#eId)}"/>
<render element="p" as="${tp}" annotation="${tp}"/>
(paragraphs do have an eId attribute)
As you can see, I tried using annotation; but these tooltips also simply display the variable literally.
I also fiddled and tried a bunch of xpath stuff, like #eId/.#eId//#eId, but I think there's some restriction in using the Content Completion Configuration File with respect to editor variables.
So is the thinking right but I am doing something wrong, or is it not the right way but there is some other way to affect the breadcrumb? Maybe with the schema?
The element display names in cc_config.xml file do not support most of the editor variables. Most of them, like ${cf} (current file) and ${tp} (total number of pages) don't make sense to be used when rendering the name of an element.
The xpath_eval would make sense - the display name of an element may depend on its attributes (e.g. the #id attribute), it's index in the document (e.g. 'Section 3'), etc. We have a feature request registered for this case and I added your vote to it.
As a partial workaround you can use a JS API to compute the display name of the element based on the element original name and its attributes:
goog.events.listen(workspace, sync.api.Workspace.EventType.BEFORE_EDITOR_LOADED, function(e) {
e.options.elementNameEnhancer = function(elemName, attrs) {
var displayString = elemName;
var attr = attrs['id'];
if (attr) {
displayString += ' (#' + attr.attributeValue + ')';
}
return displayString;
};
});

Disabling add, edit, delete buttons

I would like to add dynamic buttons in my Angular asp.net core web api. When the status of product is "Z", functionality like add, edit and delete should be not visible.
I have one method which works but in second case I do not know how to use it. Please find below example of working method:
Component.service.ts
getDisabledAddEditDel(model:Component,mode: string)
{
if(model && mode != 'View' && mode !='Add' && model.StatusOfProduct === 'Z')
{
return false;
}
return true;
}
In above case StatusOfProduct exist in model Component. I would like to use this method in a second case but in second model, StatusOfProduct does not exist. How can I use StatusOfProduct from Component in other service (model). Is there any other way than adding StatusOfProduct to my second service and model?
Thank you.
You can add the condition directly in the html. The [disabled] directive if set to true will disable the given button.
<button [disabled]="model && mode != 'View' && mode !='Add'
&& model.StatusOfProduct === 'Z'" (click)="add()">ADD</button>
You can also achieve the same result with your function
<button [disabled]="getDisabledAddEditDel(model,mode)"
(click)="add()">ADD</button>

Wordpress change comment error message

is there any way to change the default wordpress message:
Error: please fill the required fields (name, email)
from "wp-comments-post.php" file? Obviously without changing it directly in this wordpress file.
Thank you!
You could use jQuery to check if any of your comment form input elements are empty, and if they are, display an error message and prevent the form from submitting.
Using #email and #author as example input elements, you could do something like this (not tested):
$('#form').submit(function() {
if ($.trim($("#email").val()) === "" || $.trim($("#author").val()) === "") {
alert('you did not fill out one of the fields');
return false;
}
});
You could take it a step further by showing an element within the comment form instead of a browser alert pop up.
Using a hidden element in your comments form markup:
<div class="error-message" style="display:none">custom error message here</div>
Then show that message when the fields are empty like this:
$('#form').submit(function() {
if ($.trim($("#email").val()) === "" || $.trim($("#author").val()) === "") {
$(".error-message").fadeIn();
return false;
}
});

Logic in JsViews css-tag

I am trying to put logic in a css-width in a data-link in jsViews. The two following approaches did not work:
{{for Items}}
...
<td id="show-keys" data-link="css-width{~root.ShowKeys ? '200px' : '400px'}">
or
{{for Items}}
...
<td id="show-keys" data-link="css-width{:~keysWidth()}">
...
<script type="text/javascript">
...
var app = {
...
helpers: {
showKeys: function () {
//debugging shows that this never gets fired
return app.ShowKeys ? '400px' : '100px';
}
How do I appropiatly base a css-value on a property so that it changes dynamically?
Here is a jsfiddle that shows a few variants: http://jsfiddle.net/BorisMoore/GZPvZ/
Your first expression missing a :
data-link="css-width{~root.ShowKeys ? '200px' : '400px'}"
should be
data-link="css-width{:~root.ShowKeys ? '200px' : '400px'}"
For the second approach, using a helper, apart from the naming of the helper (I think you meant it to be keysWidth - as #BKimmel points out) - you need to declare the fact that it is a computed observable with a dependency on ~root.showKeys - which you do like this:
function keysWidth() {
return app.showKeys ? '400px' : '100px';
}
keysWidth.depends = "~root.showKeys"; // or you can write ... = [app, "showKeys"]
Alternatively you can not declare the dependency, but pass it in as an argument:
data-link="css-width{:~keysWidth3(~root.showKeys)}"
Helpers can be declared globally, or passed in with the link call.
See the jsfiddle for details...
Update: There are now some new samples that cover CSS and class binding. There is a tutorial sequence on data-linking, which includes this page on data-linking class, this on on toggling class, and this one on linking to CSS attributes.
At a glance here, I notice two things;
For the second setup, I wouldn't expect that to work as written... your helper function is called showKeys, but in the template you are calling a function called keysWidth... maybe that was just a transcription mistake, but it definitely won't work like that. Change the names so they match (case-sensitive, as always in JS).
Make sure your helpers are actually getting loaded... e.g. $.helpers({helperfunction: function() {...}}) ... sometimes that can cause issues.

Resources