Review data section at end of long form (Blazor html)? - html

I have several long form sections in a Blazor html project. After a user has completed all of the fields, I would like there to be a section at the very end where they can double-check the data they have inputted before submitting. Can anyone give me the basic structure/advice of how to do this?

isFilled -> is just a variable to hold the current state.
#if(isFilled == false){
<<<<<<Here is the data entery>>>>>>>>
<button #OnClick="next">Next</button>
}
#if(isFilled == true){
<section>
<<<<<<<<<<<Review the data here>>>>>>>>>
<button #OnClick="confirm">Confirm</button>
<button #OnClick="edit">Edit</button>
</section>
}
Code section :
#Code{
private bool isFilled;
protected override void OnInitialized()
{
isFilled = false;
}
private void next(){
isFilled = ture;
}
private void edit(){
isFilled = false;
}
private void confirm(){
}
}

Related

Routing to named element in Blazor (use anchor to navigate to specific element)

I cannot use an HTML anchor to navigate to a specific HTML element of a page in the Blazor Server. For example:
#page "/test"
<nav>
<!-- One version I've tried -->
Section2
<!-- Another version I've tried -->
<NavLink href="#section2">Section2</NavLink>
</nav>
#* ... *#
<h2 id="section2">It's Section2.</h2>
#* ... *#
When I click the link to Section2, I get redirected to the route http://localhost:5000/test#section2, however, will be at the top of the page. In my opinion, the browser should scroll down to the proper element, as specified by the Element Selector, but it can't.
Does it have to be done in a special way in Blazor?
I use Blazor 6 in .Net6 with Visual Studio 2022 (ver:17.0.2).
After loading a page, a browser automatically scrolls to the element identified by its id in the fragment part of the URL. It does the same when you click on an anchor with an href of the kind #element-id.
The page load behavior doesn't work for a Blazor Server because the element doesn't exist yet on page load.
The solution is to manually create a scroller using javascript and a razor component:
First of all, create a razor component like this
#inject IJSRuntime JSRuntime
#inject NavigationManager NavigationManager
#implements IDisposable
#code {
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await ScrollToFragment();
}
public void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
}
private async void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
await ScrollToFragment();
}
private async Task ScrollToFragment()
{
var uri = new Uri(NavigationManager.Uri, UriKind.Absolute);
var fragment = uri.Fragment;
if (fragment.StartsWith('#'))
{
// Handle text fragment (https://example.org/#test:~:text=foo)
// https://github.com/WICG/scroll-to-text-fragment/
var elementId = fragment.Substring(1);
var index = elementId.IndexOf(":~:", StringComparison.Ordinal);
if (index > 0)
{
elementId = elementId.Substring(0, index);
}
if (!string.IsNullOrEmpty(elementId))
{
await JSRuntime.InvokeVoidAsync("BlazorScrollToId", elementId);
}
}
}
}
Then add this javascript code somewhere before the Blazor script renders. You can wrap it with script tags and place it in the head.
function BlazorScrollToId(id) {
const element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
}
Finally implement it in your pages if needed. You can also place it inside your layouts, so it will work for every page you create.
#page "/"
<PageTitle>Index</PageTitle>
<a href="#my-id">
<h1>Hello, world!</h1>
</a>
<SurveyPrompt Title="How is Blazor working for you?" />
<div style="height: 2000px">
</div>
<div id="my-id">
Hello!
</div>
<AnchorNavigation />
Source: link
You can also use an ElementReference and FocusAsync which uses the built in Blazor JS. To use it you need to use a small hack to make the component "Focusable" which is to set a tabindex. I've used a span but you can use what you like. I've used #alessandromanzini's code to get the element from the NavigationManager.
Here's a component:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;
using System.Diagnostics.CodeAnalysis;
namespace SO75358165;
public class Bookmark : ComponentBase, IDisposable
{
private bool _setFocus;
[Inject] private NavigationManager NavManager { get; set; } = default!;
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public string? BookmarkName { get; set; }
[DisallowNull] public ElementReference? Element { get; private set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "span");
builder.AddAttribute(2, "tabindex", "-1");
builder.AddContent(3, this.ChildContent);
builder.AddElementReferenceCapture(4, this.SetReference);
builder.CloseElement();
}
protected override void OnInitialized()
=> NavManager.LocationChanged += this.OnLocationChanged;
protected override void OnParametersSet()
=> _setFocus = this.IsMe();
private void SetReference(ElementReference reference)
=> this.Element = reference;
private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
{
if (this.IsMe())
{
_setFocus = true;
this.StateHasChanged();
}
}
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (_setFocus)
await this.Element!.Value.FocusAsync(false);
_setFocus = false;
}
private bool IsMe()
{
string? elementId = null;
var uri = new Uri(this.NavManager.Uri, UriKind.Absolute);
if (uri.Fragment.StartsWith('#'))
{
elementId = uri.Fragment.Substring(1);
return elementId == BookmarkName;
}
return false;
}
public void Dispose()
=> NavManager.LocationChanged -= this.OnLocationChanged;
}
Here's my test page:
#page "/"
<PageTitle>Index</PageTitle>
<NavLink href="#me">To me</NavLink>
<h1>Hello, world!</h1>
<h1>Hello, world!</h1>
<h1>Hello, world!</h1>
//.....
<h1>Hello, world!</h1>
<Bookmark BookmarkName="me" >
<h1 id="me">Focus on Me</h1>
</Bookmark>

How do I restart a component in a Blazor page

I have a Syncfusion SfDialog in my code and I need the component in the content to restart every time the dialog is open. So far I have tried this:
<SfDialog Visible="_dialogTripRunAutoRoute" Width="75%" ShowCloseIcon="true" IsModal="true" AllowPrerender="true">
<DialogEvents Closed="#CloseDialogTripRunAutoRoute"></DialogEvents>
<DialogTemplates>
<Content>
#_tripRunAutoRoute
</Content>
</DialogTemplates>
<DialogPositionData X="center" Y="top"></DialogPositionData>
</SfDialog>
private async Task ToggleDialogTripRunAutoRoute(){
_tripRunAutoRoute = new TripRunAutoRoute();
_tripRunAutoRoute.ModelTripRun = TripOps.TripRunAutoRouteFormModel;
await InvokeAsync(StateHasChanged);
_dialogTripRunAutoRoute = !_dialogTripRunAutoRoute;
}
The result is
Assumption. #_tripRunAutoRoute is just a plain old RenderFragment.
You can't "restart" a component. The Renderer controls the component's lifecycle, not you. Any attempt to reset its state internally will be reverted the next time the page renders.
Move the toggle parameter outside the control like this:
#if(_dialogTripRunAutoRoute)
{
SfDialog stuff
}
Now the Renderer will remove the component from the render tree when _dialogTripRunAutoRoute is false, and create a new instance when it's true.
You can use the Opened and Closed event of the Dialog control to re render your component added in the Dialog content. Refer the API and code below,
<div class=" col-lg-8 control-section sb-property-border" id="target" style="height:350px;">
<div>
#if (this.ShowButton)
{
<button class="e-btn" #onclick="#OnBtnClick">Open</button>
}
</div>
<SfDialog Width="335px" IsModal="true" #bind-Visible="Visibility" AllowPrerender="true" CssClass="dialog-medium">
<DialogTemplates>
<Header> Software Update </Header>
<Content>
#if(DialogBool)
{
#DialogContent
<div>#count</div>
}
</Content>
</DialogTemplates>
<DialogButtons>
<DialogButton Content="OK" IsPrimary="true" OnClick="#DlgButtonClick" />
</DialogButtons>
<DialogEvents OnOpen="#DialogOpen" Closed="#DialogClose"></DialogEvents>
<DialogAnimationSettings Effect="#DialogEffect.None"></DialogAnimationSettings>
</SfDialog>
#code {
SfCheckBox<bool> CheckboxObj;
public int count { get; set; } = 0;
public bool DialogBool { get; set; } = false;
public string DialogContent { get; set; } = "";
private bool Visibility { get; set; } = true;
private bool ShowButton { get; set; } = false;
private void DialogOpen(Object args)
{
this.ShowButton = false;
DialogBool = true;
}
private void DialogClose(Object args)
{
this.ShowButton = true;
DialogBool = false;
}
private void OnBtnClick()
{
this.Visibility = true;
DialogContent = "content added";
count++;
}
private void DlgButtonClick()
{
this.Visibility = false;
}
}
API Link: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Popups.DialogEvents.html#Syncfusion_Blazor_Popups_DialogEvents_Opened
I need the component in the content to restart every time the dialog is open
You can make Blazor restart the component by assigning the key attribute to the component. When you change the key, Blazor re-creates the component in the DOM, thus, you can call it as restarted or rebooted.
<ComponentInTheContent #key="#(componentId)">
</ComponentInTheContent>
#code {
private Guid componentId = Guid.NewGuid();
private async Task CalledWhenDialogIsOpened()
{
// stuff
// this change of id will make Blazor re-create
// the component in the DOM as it sees it as a new component.
componentId = Guid.NewGuid();
}
}

How to switch between several sections in angular component template based on condition

I have a couple of sections in my component template file that I'd like to switch between based on certain conditions.
<section *ngIf="guest==true">
<h1>Guest</h1>
<button (click)="goToLogin()">Login</button>
<button (click)="goToRegistration()">Register</button>
</section>
<section *ngIf="login==true">
<h1>Login</h1>
<button (click)="goToRegistration()">Register</button>
<button (click)="goToGuest()">Guest</button>
</section>
<section *ngIf="register==true">
<h1>Register</h1>
<button (click)="goToLogin()">Login</button>
<button (click)="goToGuest()">Guest</button>
</section>
My component.ts file looks something like this... Initially guest is set to true and the rest of the sections are hidden.
public login = false;
public register = false;
public guest = true;
private reset() {
this.login = false;
this.register = false;
this.guest = false;
}
public goToLogin() {
this.reset();
this.login = true;
}
public goToRegister() {
this.reset();
this.register = true;
}
public goToGuest() {
this.reset();
this.guest = true;
}
My desired result is such that when a user clicks on a button, the relevant section is brought into view and the rest hidden. The code you see doesn't work. How do I get this to work and is there a better way to do this? I'd really like to know.
This doesn't fix your problem as it seems to have already been solved. This instead provides another alternative solution to what you're trying to achieve. You can also use the ngSwitch structural directive which can achieve the same result but in a simpler way. It'll reduce the logic your component.ts file to one method.
component.html
<ng-container [ngSwitch]="state">
<section *ngSwitchCase="'guest'">
<h1>Guest</h1>
<button (click)="goTo('login')">Login</button>
<button (click)="goTo('register')">Register</button>
</section>
<section *ngSwitchCase="'login'">
<h1>Login</h1>
<button (click)="goTo('register')">Register</button>
<button (click)="goTo('guest')">Guest</button>
</section>
<section *ngSwitchCase="'register'">
<h1>Register</h1>
<button (click)="goTo('login')">Login</button>
<button (click)="goTo('guest')">Guest</button>
</section>
</ng-container>
component.ts
export class AppComponent {
public state: string = 'login';
public goTo(state) {
this.state = state;
}
}
https://angular.io/api/common/NgSwitch
https://stackblitz.com/edit/angular-skxolq
You've placed all buttons that switch off/on dependent on them sections (related ngIf directive) inside of that sections:
<section *ngIf="guest==true">
<h1>Guest</h1>
<button (click)="goToLogin()">Login</button>
<button (click)="goToRegistration()">Register</button>
</section>
And goToLogin should switch off/on section (inside of which the button Login is placed):
// initially it's false
public login = false;
public goToLogin() {
this.reset();
this.login = true;
}
I guess all buttons that switch off/on related blocks should be out of them like so (also use *ngIf="guest"):
<section *ngIf="guest">
<h1>Guest</h1>
<button (click)="goToRegistration()">Register</button>
</section>
<button (click)="goToLogin()">Login</button>
Since you are checking against a boolean, you could just do
<section *ngIf="guest">
the same for other two conditions as well
Try this
component.html
<section>
<h1 *ngIf="guest">Guest</h1>
<h1 *ngIf="login">Login</h1>
<h1 *ngIf="register">Register</h1>
<button (click)="goToLogin()" *ngIf="guest || register">Login</button>
<button (click)="goToRegister()" *ngIf="login || guest">Register</button>
<button (click)="goToGuest()" *ngIf="register || login">Guest</button>
</section>
component.ts
public login = false;
public register = false;
public guest = true;
private reset() {
this.login = false;
this.register = false;
this.guest = false;
}
public goToLogin() {
this.reset();
this.login = true;
}
public goToRegister() {
this.reset();
this.register = true;
}
public goToGuest() {
this.reset();
this.guest = true;
}
I hope this will be useful

How to call Update function's code by button click

How can I call the codes, inside the Update function using a public method?
What I need to archive is, calling Update using another function.
So that Update triggers using that other method.
One more thing, code should run only when a button long press.
Many Thanks four help
using UnityEngine;
using System.Collections;
public class CarController : MonoBehaviour
{
public float speed = 1500f;
public float rotationSpeed = 15f;
public WheelJoint2D backWheel;
public WheelJoint2D frontWheel;
public Rigidbody2D rb;
private float movement = 0f;
private float rotation = 0f;
void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
void FixedUpdate()
{
if (movement == 0f)
{
backWheel.useMotor = false;
frontWheel.useMotor = false;
}
else
{
backWheel.useMotor = true;
frontWheel.useMotor = true;
JointMotor2D motor = new JointMotor2D { motorSpeed = movement, maxMotorTorque = 10000 };
backWheel.motor = motor;
frontWheel.motor = motor;
}
rb.AddTorque(-rotation * rotationSpeed * Time.fixedDeltaTime);
}
//public void Rotate()
//{
// rotate = true;
// print("aa");
//}
//public void Move()
//{
// rotation = Input.GetAxisRaw("Horizontal");
// movement = -Input.GetAxisRaw("Vertical") * speed;
//}
}
Those are actually two questions.
1. A long press button
The Unity UI.Button hasn't per se a method for a long press but you can use the IPointerXHandler interfaces for implementing that on your own:
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
// RequireComponent makes sure there is Button on the GameObject
[RequireComponent(typeof(Button))]
public class LongPressButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
private void Awake()
{
ResetButton();
}
// set the long press duration in the editor (in seconds)
public float LongPressDuration = 0.5f;
// Here you reference method just like in onClick
public UnityEvent onLongPress;
private float _timer;
private bool _isPressed;
private bool _pressInvoked;
private void Update()
{
// prevent multiple calls if button stays pressed
if (_pressInvoked) return;
// if button is not pressed do nothing
if (!_isPressed) return;
// reduce the timer by the time passed since last frame
_timer -= Time.deltaTime;
// if timeout not reached do nothing
if (!(_timer <= 0)) return;
// Invoke the onLongPress event -> call all referenced callback methods
onLongPress.Invoke();
_pressInvoked = true;
}
// reset all flags and timer
private void ResetButton()
{
_isPressed = false;
_timer = LongPressDuration;
_pressInvoked = false;
}
/* IPointer Callbacks */
// enable the timer
public void OnPointerDown(PointerEventData eventData)
{
_isPressed = true;
}
// reset if button is released before timeout
public void OnPointerUp(PointerEventData eventData)
{
ResetButton()
}
// reset if cursor leaves button before timeout
public void OnPointerExit(PointerEventData eventData)
{
ResetButton();
}
}
This script has to be placed next to the Button component.
You don't reference the callback method(s) in the Button's
onClick but instead in this LongPressButton's onLongPress
and don't forget to adjust LongPressDuration also in the inspector.
Example
2. Calling CarController's Update
I don't know why you want this (I guess you disabled the component but want to call Update anyway)
Solution A
In order to be able to reference that method in the Inspector there are a few options:
Simply make your Update method public
public void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
wrap the content of Update in another public method and use that one instead:
private void Update()
{
DoUpdateStuff();
}
public void DoUpdateStuff()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
the other way round (how you requested it) - call Update from another public method:
private void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
public void DoUpdateStuff()
{
Update();
}
So all that's left is referencing the CarController's Update or DoUpdateStuff method in the LongPressButton's onLongPress event.
Solution B
Alternatively you could add that callback directly on runtime without referencing anything nor making the callback method public so you could directly use private void Update without a wrapper method.
Drawback: For this method you somehow have to get the reference to that LongPressButton in your CarController script instead
public class CarController : MonoBehaviour
{
// Somehow get the reference for this either by referencing it or finding it on runtime etc
// I will asume this is already set
public LongPressButton longPressButton;
private void Awake()
{
// make sure listener is only added once
longPressButton.onLongPress.RemoveListener(Update);
longPressButton.onLongPress.AddListener(Update);
}
private void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
private void OnDestroy()
{
// clean up the listener
longPressButton.onLongPress.RemoveListener(Update);
}
//...
}
Thanks for your descriptive reply. What I did was change my script to following and added Event Trigger component. Then call the public functions accordingly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarMve : MonoBehaviour
{
bool move = false;
bool moveR = false;
public Rigidbody2D rb;
public float speed = 20f;
public float rotationSpeed = 2f;
private void FixedUpdate()
{
if (move == true)
{
rb.AddForce(transform.right * speed * Time.fixedDeltaTime * 100f, ForceMode2D.Force);
}
if (moveR == true)
{
rb.AddForce(transform.right *- speed * Time.fixedDeltaTime * 100f, ForceMode2D.Force);
}
}
/* Will be used on the UI Button */
public void MoveCar(bool _move)
{
move = _move;
}
public void MoveCarR(bool _moveR)
{
moveR = _moveR;
}
}

Flex, pushing message, ServiceAdapter, BlazeDS

I have Flex 3.6A + BlazeDS + java6 webapp.
I want to push message from server that must be intercepted by the client (.mxml page). Googlin around I manage to build the follow example:
public class TestMessaging extends ServiceAdapter {
private String previousMsg = "";
private volatile boolean running;
private Message createTestMessage() {
AsyncMessage msg = new AsyncMessage();
msg.setDestination("RandomDataPush");
msg.setClientId(UUIDUtils.createUUID());
msg.setMessageId(UUIDUtils.createUUID());
msg.setBody(BarValues.STATUS);
return msg;
}
#Override
public void start(){
super.start();
Thread messageSender = new Thread(){
public void run(){
running = true;
while(running){
sendMessageToClients(createTestMessage());
secondsToSleep(3);
}
}
};
messageSender.start();
}
/**
* #see flex.messaging.services.ServiceAdapter#stop()
*/
#Override
public void stop(){
super.stop();
running = false;
}
public void sendMessageToClients(Message msg) {
if (!msg.getBody().equals(previousMsg)) {
previousMsg = msg.getBody().toString();
((MessageService) getDestination().getService()).pushMessageToClients(msg, false);
}
}
#Override
public Object invoke(Message message) {
if (message.getBody().equals("stop")) {
running = false;
} else if (message.getBody().equals("start")) {
start();
}
return null;
}
private void secondsToSleep(int seconds) {
try{
Thread.sleep(seconds * 1000);
}catch(InterruptedException e){
System.out.println("TestServiceAdapter Interrupted while sending messages");
e.printStackTrace();
}
}
}
In the .mxml I have:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%" creationComplete="init()">
<mx:Script>
<![CDATA[
private function messageHandler(message:IMessage):void {
randomNumbers = message.body as String;
if (randomNumbers == null) {
var msg:AsyncMessage = new AsyncMessage();
msg.body = "stop";
producer.send(msg);
} else Alert.show(randomNumbers.toString());
}
private function init():void {
var msg:AsyncMessage = new AsyncMessage();
msg.body = "stop";
producer.send(msg);
consumer.subscribe();
}
private function start():void {
var msg:AsyncMessage = new AsyncMessage();
msg.body = "start";
producer.send(msg);
consumer.subscribe();
}
private function handleFault(event:MessageFaultEvent):void {
Alert.show(event.faultString);
}
private function ack(event:MessageAckEvent):void {
if (event.message.body != null) {
randomNumbers = event.message.body as String;
Alert.show(randomNumbers.toString());
}
}
<mx:Producer id="producer" destination="RandomDataPush" acknowledge="ack(event)"/>
<mx:Consumer id="consumer" destination="RandomDataPush" message="messageHandler(event.message)" />
</mx:Application>
Problems are:
1) Whitout a thread I can't manage to push messages
2) The thread starts automatically when I alunch the application. To prevent this I send the "stop" when the init() method of the flex page is called (but is really orrible)
What I want to do is: when a java query is executed (or a complex elaboration starts) I want to start the service and send messages calling manually the sendMessageToClients method (without thread if is it possible) and, when the query or the elaboration ends, stop the service.
Can you help me?
Thanks all