How to hide a component menu in Angular - html

I developing a login page and i wouldn't like to show my menu in this page. Currently im calling the component menu in app-component. I would like to know what is the best practice to hide it.
<app-toolbar></app-toolbar>
<div class="row d-flex justify-content-center">
<div class="col-md-8">
<router-outlet></router-outlet>
</div>
</div>
Thanks!

For me, I simply did an *ngIf on my menu bar element. The ngIf referenced a function that would check if the user was logged in or not.
getLoggedInStatus() {
if (localStorage.getItem('userToken') != null) {
return true;
}
else {
return false
}
}
You can see I'm checking local storage for a token that is set on login
<div class="col hide-on-med-and-down l2 no-padding" *ngIf="getLoggedInStatus()">
And there is the menu element wrapper with the if statement. Should be said that I don't know if this is best practice, but I was new when writing my app and by the time I got to login/authentication I was WAY too far down the rabbit hole to re-write things

The best way to hide/show any element in Angular is to use the *ngIf directive. Do note that the component/element will bee hidden/shown based on a condition which you will have to provide.

Related

Mudblazor Select "broken" on Popover

I have a MudSelect on a MudPopover but I encounter a somewhat weird behavior when using the select. The select dropdown will not appear over everything else as it should, but instead, it will be layered behind /underneath other components and is unclickable. The confusing thing about this is that a simple reload (when opening the page) fixes the issue. Does somebody know what triggers the "broken" behavior and how it is then fixed by reloading? Or does somebody know how to fix it without forcing a reload upon entering the page?
when it is broken
how it should normally look
<MudPopover Open="#_open" RelativeWidth="true" Fixed="true">
<div class="d-flex flex-column">
<EditForm Model="#items" Context="itemUpload">
<MudSelect #bind-Value="selectedH" Margin="Margin.Dense" Variant="Variant.Outlined" Label="whatever" AnchorOrigin="Origin.BottomCenter">
#foreach (var item in items)
{
<MudSelectItem Value="#item.id">#item.name</MudSelectItem>
}
</MudSelect>
</EditForm>
<MudButton Disabled="#uploading" OnClick="Upload" Variant="Variant.Filled" Color="Color.Primary">
#if (uploading)
{
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
<MudText Class="ms-2">Processing</MudText>
}
else
{
<MudText>Upload</MudText>
}
</MudButton>
<MudButton OnClick="#ToggleOpen" Class="ml-auto mr-n3 mb-1" Color="Color.Error">Schließen</MudButton>
</div>
</MudPopover>
#InCo placed this in the comments, but it appears to be the best solution I have seen, so I pulled this out into an answer. Instead of using MudPopover, use MudDialog. It solves the Z-Index issue for MudSelect as well as MudDatePicker

Removing events from HTML tag (ondrag) programmatically with #if statements

I am building an interactive Blazor Server UI where you can drag and drop cards into different orders. The UI is working fine, but I want to make it switchable so that I can enter and leave "sort mode." When not in sort mode, I thought it may be best to remove the ondrag events completely from the app to make it more optimized.
Here is the functioning code:
<div class="row" ondragover="event.preventDefault();">
#foreach (var photo in files)
{
<div class="col-xl-3 col-lg-4"
draggable="true" //This doesn't seem to be settable by a bool
#key="photo.Id"
tabindex="1"
#ondragstart="#(()=> StartDrag(photo))"
#ondragover="#(()=> DragOver(photo))">
<div class="card">Card contents here</div>
</div>
}
</div>
I want to remove the ondragover, #ondragstart="#(()=> StartDrag(photo))", and #ondragover="#(()=> DragOver(photo))" sections
My first thought was to wrap each opening <div> in an if/else and have two versions, one with the additional code and one without, but even though there are two opening <div>s in an if/else, the compiler gives an error saying there's an opening div without a closing.
#if (isSortOn)
{
<div class="row" ondragover="event.preventDefault();"> // ERROR - No closing </div>
}
else
{
<div> class="row">
}
[...OTHER STUFF HERE...]
</div> // This should be the closing div
Since that didn't work, I tried to remove the methods programmatically within the <div> with if/else, but I got errors similar to below:
<div class="row" #(isSortOn ? ondragover="event.preventDefault();" : "")>
//ERROR- can't do #codeblock inside tag
<div class="row" ondragover=#(isSortOn ? "event.preventDefault();" : "")>
//ERROR- sees event as string and not proper event/
How can I remove this functionality and use if/else to control these tags?
EDIT/CLARIFICATION: A user had suggested setting draggable="#isSortOn" but that doesn't seem to work. First, the flag doesn't appear to actually be necessary for the code to function. Second, for some reason if I set it to a bool toggling the bool doesn't actually toggle the behavior (not sure why). Third, if I set draggable="false" in the card's outer <div> and inner <img> tags, I can disable dragging. However, if you highlight some text, you can then drag things around and cause the events to re-fire. Not sure exactly how the draggable property works, but it seems very fragile.
Are you sure you're not running into something funky with Visual Studio? I'm able to run your second example code just fine with .NET 6 and Visual Studio 2022.
// Index.razor
<div class="row" #(isSortOn ? onclick="window.alert('hello')" : string.Empty)>
Hello
</div>
#code {
public bool isSortOn { get; set; } = true;
}

Embedded view not showing when switching between views using ngIf

My component A has a child component B. On start up, A shows up because of conditition in *ngIf. A uses an EmbeddedView show show image thumbnails. A also has a button which when clicked changes the condition of *ngIf and shows B (because B shows on some other condition of *ngIf). If a button in B is pressed then A shows back again.
A's html is something like
<div *ngIf="this.tabType == this.questionTab" id="form-div-question" class="body__div--background">
....
<ng-template #thumbnailTemplate let-context="context">
<div id="{{context.divId}}">
<button id="{{context.buttonId}}" type="button" data-toggle="modal" (click)="showEnlargeImage(context)">
<img id="{{context.imgId}}" src="{{context.imgSrc}}"/>
</button>
<a *ngIf="this.isEditing" href="javascript:void(0)" id="{{context.closeId}}" (click)="deleteThumbnailFromContainer(context)"></a>
</div>
</ng-template>
...
<div id="image-thumbnail-container">
<ng-container #thumbnailContainer ></ng-container>
</div>
</div>
<div *ngIf="this.tabType == this.submittedAnswerTab" id="form-div-submitted-answer" class="body__div--background">
<b-component #bComponent [someInput]="..." (someEventFromB)="switchToQuestionTab($event)"></b-component>
</div>
The EmbeddedView in A is access as follows
#ViewChild("thumbnailContainer",{read:ViewContainerRef})
thumbnailContainerRef:ViewContainerRef;
What I am noticing is that on start up A shows fine including its embedded view. Then B also shows when the button in A is clicked. But when the view switches back to A then the embedded view doesn't show up!! (rest of A shows up correctly). I tried to force recreating the embedded view, I get error that the reference to the container is not defined (i.e.thumbnailContainerRef is undefined).
I also notice that when B is shown, it seem to be initiated everytime but when A is shown, it is not reinitialised everytime (maybe because B is child and A is parent)
Why is the container reference becoming undefined?
Taking inspiration from Angular 2 Show and Hide an element and What is the difference between *ngIf and [hidden]?
I seem to have solved the problem by using [hidden] instead of ngIf of A component.
<div [hidden]= "this.tabType != this.questionTab" ...>
</div>
<div *ngIf="this.tabType == this.submittedAnswerTab" id="form-div-submitted-answer" class="body__div--background">
<b-component #bComponent [someInput]="..." (someEventFromB)="switchToQuestionTab($event)"></b-component>
</div>
It seems that when '*ngIf' is false for A, Angular removes the embedded view and it doesn't get created again which seem to to be the reason why the ViewContainerRef is undefined when I switch back to A. Using [hidden] just hides A. Maybe there is code smell in my implementation but hey, I am still learning!

How to add a custom directive div after nth ng-repeat item

In my code i have a bunch of items rendered by ng-repeat.
These items use the bootstrap class col-md-3
and i'd like to add a feature which allows the user to see a large detail panel by clicking on one of these items.
However i'd like to accomplish it by having only one detail panel in my DOM and moving it around.
The html is like this:
<div ng-repeat="thing in thingsCtrl.things">
<thing-widget class="col-md-3"></thing-widget>
</div>
<thing-detail ng-show="thingsCtrl.showDetail" class="col-md-12"> </thing-detail>
any chance to accomplish?
Thanks in advance.
You could try moving the thing-detail inside the ng-repeat and use $index to add it or not.
<div ng-repeat="thing in thingsCtrl.things">
<thing-widget class="col-md-3"></thing-widget>
<thing-detail ng-if="$index === nth" ng-show="thingsCtrl.showDetail" class="col-md-12"> </thing-detail>
</div>

Angular js tabs content HTML tags not rendering

I have one angularjs application. In that application if we click button we are displaying some content which have tabs. By clicking each tab corresponding data will be fetch and need to display there. So data i am getting dynamically. But problem is in below example, i have HTMl tags in content(EX:- "address":"<b>NewYork</b>"). But when i click address tab, it is displaying like <b>NewYork</b>,instead i need NewYork Kindly suggest me
$scope.tabs = [
{ title:'id', content:data[0].id, active:true },
{ title:'name', content:data[0].name,active:false},
{ title:'address', content:$sce.trustAsHtml(data[0].address),active:false},
{ title:'pin', content:data[0].pin,active:false}
];
<ul class="nav nav-tabs">
<li ng-repeat="tab in tabs" ng-class="{active: tab.active}" >
{{tab.title}}
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade in" ng-repeat="tab in tabs" ng-class="{active: tab.active}" style="width:100%">
{{tab.content}}
</div>
</div>
You can solve this by using to_trusted filter
and add filter in your js side
angular.module("app", [])
.controller("ctrl", function ($scope) {
//some code
}).filter('to_trusted', ['$sce', function ($sce) {
return function(text) {
return $sce.trustAsHtml(text);
};
}]);
By default angular sanitizes your values to display any HTML tags as text, for obvious security reasons. If you want to include HTML from your objects in your templates, you can use the ng-bind-html="yourvalue" directive on your HTML elements, ie:
<span ng-bind-html="yourvalue"></span>
Or specifically for your case:
Keep in mind though that this isn't really a best practice in angular (tempting though it is, I've used it too often myself already). It all depends on your particular situation of course, but in general you might want to include this kind of markup in your template and/or include some property in your model with some significance and adjust your display based on that. For example, if city.isFavourite is true, you could conditionally add a favourite CSS class to it in your template.
To wrap it up, this page goes into some safety considerations when using HTML verbatim in your template: AngularJS API for $sanitize
Thank you so much guys. It is working fine now. I kept like below.
<div ng-bind-html="tab.content"></div>