How to target specific div with Blazor components? - html

I have a top-row div a follows:
<div class="top-row px-3">
<b>App:<i>Title</i></b>
<!-- wait for it ... -->
<div class="menu">
Menu Bar Here
</div>
</div>
I am going to have several MenuBar components that will swap out in the div class menu with a button click. How do I target that div with a Blazor component?
Update
I think I found a solution by Chris Sainty.
Edit
To clarify what I intend to accomplish:
I have 2 components:
<MenuBar1 />
<MenuBar2 />
Both contain different html to construct a simple menu bar. I have navigational links that, when clicked, will raise the onClick event.
How, when the link is clicked, can I swap out the MenuBar components?

Blazor doesn't use Javascript strategy.
To do that you have to mix HTML with code.
<div class="top-row px-3">
<b>App:<i>Title</i></b>
<!-- wait for it ... -->
<div class="menu">
#if (Version == "v1")
{
<p>version 1</p>
}
else if (Version == "v2")
{
<p>version 2</p>
}
</div>
</div>
For dynamic menu add a file in shared folder.
The file name = the class name
For example MenuButton.razor
#inject NavigationManager navManager
<button #onclick="(e)=>navManager.NavigateTo(route)">#(label)</button>
#code {
[Parameter]
public string label { get; set; }
[Parameter]
public string route { get; set; }
}
To consume this componant
<div class="top-row px-3">
<b>App:<i>Title</i></b>
<!-- wait for it ... -->
<div class="menu">
<MenuButton label="Choice 1" route="/route1" />
<MenuButton label="Choice 2" route="/route2" />
</div>
</div>

Related

Passing data to a modal in Blazor

Is there some way to transfer multiple data from one page to a modal using Razor syntax? Example I have a table with several columns and rows. In one of the columns there is a button that you can use to edit the data. I want the data from this line to be transfered over into the modal so that I can edit it.
One possibility is to do everything in a single page: the grid and the dialog. (This dialog is certainly a div).
#page "/{Langue}/OrderList"
<div class="content">
<div class="container">
<Components.Grid
Id="grid-order-list"
ListViewRecords = "new List<int> { 20, 50, 100 }"/>
</div>
</div>
#if (LineDetails != null)
{
<!-- Modal Large -->
<div class="modal fade" id="large-modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><i class="fa fa-times"></i></button>
<h6 class="modal-title">#ModalTitle</h6>
</div>
<div class="modal-body text-center">
<div class="modal-body-inside" style="height: 85vh; overflow-y: auto; padding: 60px 50px 70px;">
<UserControls.LineDetail Source="LineDetails " />
</div>
</div>
</div>
</div>
</div>
<!-- /.modal -->
}
#code {
private MyNameSpace.LineDetailsClass LineDetails;
}
As you can see, as long as LineDetails is null, the user see only the table. When clicking on the details button, you have to populate LineDetails. So the modal will be shown. LineDetails should be binded to somme textboxes, ... When the user clicks on a button in the modal, you get the needed info in LineDetails and you reset it to null.
Suppose that your class name is Person, It is your Button code :
foreach(var item in Items)
{
...
<td><button type="button" #onclick="#Update(item)">Edit</button></td>
...
}
Now we have a model for the Selected Item like this :
#code{
Person SelectedItem {get;set;}
void Update(Person selectedItem)
{
SelectedItem = selectedItem;
}
Now you can access you SelectedItem everywhere include modals.
Guy, Henk and Ali all have the right idea. I'd like to add, though, that you can add #onclick to almost ANYTHING-- a div, a table row, etc.
The general pattern is to have a List<SomeClass> AllItems, then a single SomeClass SelectedItem, then a null check.
YourModalControl.razor
<div>Show something from SelectedItem: #SelectedItem.DisplayString</div>
<button #onclick="CloseMe">Close</button>
#code{
[Parameter]
public SomeClass SelectedItem {get; set;}
[Parameter]
public EventCallback<SomeClass> SelectedItemChanged{get; set;}
async Task CloseMe(){
SelectedItem = null;
SelectedItemChanged.InvokeAsync(SelectedItem);
}
}
ConsumingPage.razor
#if (SelectedItem is not null){
<YourModalDisplayControl #bind-SelectedItem="SelectedItem" />
}
#else foreach (var item in AllItems){
<div #onclick="()=> SelectedItem = item">#item.DisplayString</div>
}
#code {
List <SomeClass> AllItems {get; set;}
SomeClass SelectedItem {get; set;}
}

Blazor .NET doesn't render a component. It just displays as HTML Markup

Recently, I came across an issue and was able to fix it by cleaning the solution. But now I have the same issue and cleaning the solution does not fix my bug.
In my project, I use modals to display forms. So, I created a modal component with an EditForm to generate a new entity in my database.
<div class="modal">
<div class="modal-body">
<div class="row">
<div class="col s12">
<h5>New Item</h5>
</div>
</div>
<div class="row">
<EditForm Model="MyEntity" OnValidSubmit="OnValidSubmit" OnInvalidSubmit="OnInvalidSubmit">
<DataAnnotationsValidator />
<ValidationSummary></ValidationSummary>
<div class="input-field fixed col s12">
<InputText id="name" #bind-Value="MyEntity.Name" />
<label class="active" for="name">Name</label>
</div>
<div class="col s12">
<button class="right btn" type="submit">Create</button>
</div>
</EditForm>
</div>
</div>
<div class="modal-footer">
<button class="modal-close btn-flat">Close</button>
</div>
</div>
#code {
[Parameter]
public MyEntityClass MyEntity {get; set;}
[Parameter]
public EventCallback<Microsoft.AspNetCore.Components.Forms.EditContext> OnValidSubmit { get; set; }
[Parameter]
public EventCallback<Microsoft.AspNetCore.Components.Forms.EditContext> OnInvalidSubmit { get; set; }
}
At the index page I would like to use the component like this:
#page "/mypage"
<MyProject.Pages.Shared.MyModalComponent MyEntity="_newMyEntity" OnValidSubmit="HandleValidSubmit" InvalidSubmit="HandleOnInvalidSubmit" />
#*
Some more HTML Code ...
*#
#code{
private MyEntityClass _newMyEntity = new MyEntityClass();
void HandleValidSubmit()
{
// Write to Database ...
}
void HandleOnInvalidSubmit()
{
// Display Errormessage to User ...
}
}
Blazor doesn't render the component, it just renders as HTML markup with the variable names:
Now to the strange part: On a different page I built a table component to display complex data and there all works fine! Did I miss something?
I'm using .NET Core 3.1 Blazor Server Side with Visual Studio 2019 Enterprise Version 16.4.4
I found the reason for this weird behaviour: Visual Studio sometimes doesn't set the build action type to "Content" on creating a new blazor component. After changing and rebuilding all works fine.

Setting the div in angular to different color on click

So though my question might sound familiar the case is a bit different. I have a screen with multiple tasks. To show the tasks I am iterating via the data and my code looks something like
<div *ngFor="let task of tasks" class="scheduleContainer inline-block shadow">
<div id="myHeader" #myHeader class="activeHeader">
{{task.title}}
</div>
<div class="detailsBox">
<div class="row">
<div class="offset-md-1 col-md-auto">
Last Date:
</div>
<div class="col-md-auto">
{{task.lastDate}}
</div>
</div>
<div class="row">
<div class="offset-md-1 col-md-auto">
Duration:
</div>
<div class="col-md-auto">
{{task.duration}}
</div>
</div>
<div class="row">
<div class="offset-md-1 col-md-auto">
Total Runs:
</div>
<div class="col-md-auto">
{{task.totalRun}}
</div>
</div>
</div>
<div class="footer">
<a [routerLink]="['edit-scheduled-tasks']">edit schedule</a>
<a [routerLink]="['view-history-scheduled-tasks']">view history</a>
<a (click)="onClick()">enable task</a>
run now
</div>
</div>
<router-outlet></router-outlet>
Now when I click on the enabled task, I would like the color of that particular div to be changed. In my component, I tried something like
onClick() {
this.myHeader.nativeElement.style.background = 'red';
}
So this did change the color but it did not change the current task but rather some other task. Suggestions?
you can access myHeader from template so you can change the color something like this
<div id="myHeader" #myHeader class="activeHeader">
Change the color by myHeader variable
</div>
<button (click)="myHeader.style.background='red'">click</button>
or you can use a property with ngStyle like this
<div [ngStyle]="{'background-color':color}" >
Another way by ngStyle
</div>
<button (click)="color='red'">click</button>
or you can use a property to toggle class with ngClass
<div [ngClass]="{'red':isClicked}" >
Set class
</div>
<button (click)="isClicked=!isClicked">Toggle class</button>
Example toggle color of taskList by useing ngClass
template
<div *ngFor="let task of taskList"
[ngClass]="{'red':selectedTasks[task.id]}"
(click)="selectedTasks[task.id]= !selectedTasks[task.id]" class="task">
{{task.name}}
</div>
or you can use button to toggle the state
<div *ngFor="let task of taskList"
[ngClass]="{'red':selectedTasks[task.id]}"
class="task">
{{task.name}}
<button (click)="selectedTasks[task.id]= !selectedTasks[task.id]">toggle {{task.name}}</button>
</div>
if you want to set the state without toggle on click event just set
the state to true like this selectedTasks[task.id] =true
component
taskList =[
{id:1 , name:'Task 01'},
{id:2 , name:'Task 02'},
{id:3 , name:'Task 03'},
{id:4 , name:'Task 04'},
{id:5 , name:'Task 05'},
];
selectedTasks = {};
stackblitz demo
Not a clean way to do, but it still works. Send an index of selected element to onClick(i) and add the color to selected div. So that you don't mess with template reference.
html
<div *ngFor="let task of tasks; let i=index;" class="scheduleContainer inline-block shadow">
<div id="myHeader" #myHeader class="activeHeader">
{{task}}
</div>
<div class="footer">
<a (click)="onClick(i)">enable task</a>
</div>
</div>
component.ts
onClick(index: number) {
document.querySelectorAll('#myHeader')[index]
.style.background = 'red';
}
DEMO
It's not a good practice to manipulate DOM directly.
Angular: Stop manipulating DOM with ElementRef!
As an alternate, It's easy to bind inline style in your Angular templates using style binding.
Since you would like the color of that particular div to be changed. Use A boolean array:
component:
export class AppComponent {
name = 'Angular';
public styleArray=new Array<boolean>(10);
onClick(i)
{
this.styleArray[i]=true;
}
}
While Iterating pass index to onClick(i) to set particular index of array true and apply style dynamically
[style.color]="styleArray[i] ? 'green':'black'"
<div *ngFor="let task of tasks; let i=index" class="scheduleContainer inline-block shadow">
<div id="myHeader" [style.color]="styleArray[i] ? 'green':'black'" class="activeHeader">
{{task.title}}
</div>
........rest of the code
<a (click)="onClick(i)">enable task</a>
Live Demo

Show or Hide Prev and next buttons based on first div and last div in angular2

I have a requirement where i want to hide or show prev and next buttons based on div tag. Basically i am creating div tags for each value of list using ngfor loop in angular2.
List I have used
appUlist:string[] = ["Calculus-1","Geometry-1","Algebra-1","Trignometry-1","Statstics-1","Arithmetic-1"]
Now i am creating a div tag for each value in the list using ngFor in html. Since there are more than 5 values in the list, i have used next and prev button so that i can see other div tags as soon as i click on next button. This part works pretty well. but i want hide prev button if i am showing the first div tag and hide next button if there are no further div tags.
Please advice me on this
Below i have posted both html and ts code
export class AppComponent{
#ViewChild('panel', { read: ElementRef }) public panel: ElementRef<any>;
public selectedDiv;
public u;
title = 'app';
name:string = 'Creating new screen for student';
public appUlist:string[] = ["Calculus-1","Geometry-1","Algebra-1","Trignometry-1","Statstics-1","Arithmetic-1"]
}
//scrolls back when clicked on prev
public onPreviousSearchPosition(): void {
this.panel.nativeElement.scrollLeft -= 20
}
//scrolls forward when clicked on next button
public onNextSearchPosition(): void {
this.panel.nativeElement.scrollBy(20,0);
}
My html code
<div #panel class="row" style="width:700px;height:300px;overflow-x: scroll;overflow: hidden;" >
<div class="col-lg-1">
<i class="fa fa-angle-double-left" style="font-size:36px;color:#1092B0" id="left" (click)="onPreviousSearchPosition()"></i>
</div>
<div class="col-lg-1 cardhover" *ngFor="let u of appUlist">
<h1>test</h1>
</div>
<div class="col-lg-1">
<i class="fa fa-angle-double-left" style="font-size:36px;color:#1092B0" id="right" (click)="onNextSearchPosition()"></i>
</div>
</div>
Below image represents the output of mycode
You can put a variable to 0 in your appComponent and increment/decrement it each time you click prev and next. If this variable is == 0 you don't show prev button, if it is equal to your list lenght - 3 you don't show the next button :
export class AppComponent{
#ViewChild('panel', { read: ElementRef }) public panel: ElementRef<any>;
public selectedDiv;
public u;
public index = 0;
title = 'app';
name:string = 'Creating new screen for student';
public appUlist:string[] = ["Calculus-1","Geometry-1","Algebra-1","Trignometry-1","Statstics-1","Arithmetic-1"]
}
//scrolls back when clicked on prev
public onPreviousSearchPosition(): void {
this.panel.nativeElement.scrollLeft -= 20
this.index--;
}
//scrolls forward when clicked on next button
public onNextSearchPosition(): void {
this.panel.nativeElement.scrollBy(20,0);
this.index++;
}
and
<div #panel class="row" style="width:700px;height:300px;overflow-x: scroll;overflow: hidden;" >
<div class="col-lg-1">
<i *ngIf="idx != 0" class="fa fa-angle-double-left" style="font-size:36px;color:#1092B0" id="left" (click)="onPreviousSearchPosition()"></i>
</div>
<div class="col-lg-1 cardhover" *ngFor="let u of appUlist">
<h1>test</h1>
</div>
<div class="col-lg-1">
<i *ngIf="idx < list.lenght - 3" class="fa fa-angle-double-left" style="font-size:36px;color:#1092B0" id="right" (click)="onNextSearchPosition()"></i>
</div>
</div>

Pass parameter from Button to Java spring MVC controller

I've been looking for something that might help me to solve this without success. What I need is just to call a Spring Controller by pressing a Button element, and pass from it a RequestParam("statusId" in this specific case). Is there a way to do this without using JavaScript?
I have the next html:
<div class="tablero col-lg-4 col-md-4 col-sm-6">
<div class="inner-content">
<div class="rate">
<div class="number">
<span>${package}</span>
<span class="text">REFERRALS</span>
</div>
</div>
<div class="description">
<h3>
<i class="fa fa-shopping-bag"></i>
PACKAGE
</h3>
<label>Paquete</label>
<button class="btn-primary" onclick="location.href='listReferred.htm' id="package">GO TO LIST</button><!--The parameter should be send from this button-->
</div>
</div>
</div>
And the Spring MVC Controller:
#SuppressWarnings("unchecked")
#RequestMapping(value="/listReferred", method=RequestMethod.GET)
public String getListReferredPage(#RequestParam int statusId, Model model) {
RestTemplate restTemplate = new RestTemplate();
String url = URL_REFERREDTYPE_JSON+statusId;
List<SearchProspectTO> searchProspectToList = restTemplate.getForObject(url, List.class, statusId);
model.addAttribute("searchProspectToList", searchProspectToList);
return "portalInternoReferidos";
}
Surround at least the button element with a form, like this:
<form action="listReferred" method="get">
<button...
</form>
Add a name and value attribute to the button:
<button name="yourButton" value="[provide status id here]">GO TO LIST</button>
Alter #RequestParam int statusId to #RequestParam(value="yourButton") int statusId.
This will work except for older IE browsers - below Version 10 I think. These versions will return 'GO TO LIST' instead of the value.
As workaround you could use a hidden input, that has to be placed inside the form section as well.