When to use #ref for child component in Blazor - razor

The parent page has two child components and a button.
On page load, the two components should be visible.
The button click should toggle their visibility.
I'm able to achieve the desired output, but would like to understand the best way.
Index.razor
#page "/"
<button #onclick="ToggleVisibility">Toggle Visibility</button>
<br />
<VisibilityComponent1 ShowComponent=visibilityState></VisibilityComponent1>
<br />
<VisibilityComponent2 #ref="visibilityComponent2"></VisibilityComponent2>
#code
{
private bool visibilityState = true;
private VisibilityComponent2 visibilityComponent2;
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
visibilityComponent2.SetVisibility(visibilityState);
}
private void ToggleVisibility()
{
visibilityState = !visibilityState;
visibilityComponent2.SetVisibility(visibilityState);
}
}
VisibilityComponent1.razor
#if (ShowComponent)
{
<h3>First Component</h3>
}
#code {
[Parameter]
public bool ShowComponent { get; set; }
}
VisibilityComponent2.razor
#if (showComponent)
{
<h3>Second Component</h3>
}
#code {
private bool showComponent;
public void SetVisibility(bool isVisible)
{
showComponent = isVisible;
StateHasChanged();
}
}
For VisibilityComponent1, I have used the Parameter approach and for VisibilityComponent2, the #ref approach.
#1. I have used OnAfterRender to make VisibilityComponent2 visible. Is this the correct way?
#2. What is the difference between these two approaches. Could you please explain when to use which with any real-time example.

I think the code answers your question:
The #ref approach for VisibilityComponent2 is much more complex. Meaning it is also more error-prone. And there isn't any benefit.
VisibilityComponent1 is more streamlined and follows the normal Blazor rendering flow.
On a side note, both approaches only make sense when VisibilityComponent1 or VisibilityComponent2 have some state to maintain. Otherwise, the most efficient solution would be:
<button #onclick="ToggleVisibility">Toggle Visibility</button>
<br />
#if(visibilityState)
{
<VisibilityComponent1></VisibilityComponent1>
<br />
<VisibilityComponent2></VisibilityComponent2>
}

#2. What is the difference between these two approaches. Could you please explain when to use which with any real-time example.
When you need to use the component as a variable you'd attach it to an #ref. Maybe pass it as a cascading value or call some method on it like visibilityComponent2.RefreshSomeData(). In your example you don't need to use the component as a variable. In doing so makes the code more complex for no reason. VisibilityComponent1 would be the way to go here.
#1. I have used OnAfterRender to make VisibilityComponent2 visible. Is this the correct way?
In your example you pretty much have to do it here because of the #ref. It will be null in OnInitialized and OnParametersSet. When your render mode is ServerPrerendered you'll generally want to put javascript and code that you only want to execute once in the OnAfterRender on the firstRender. If your render mode is Server you can get away with doing some things earlier in the life cycle (especially javascript). In Server mode each portion of the life cycle is only executed once.

Related

Junit testing in java for void methods

How to write test case for this function in a binary search tree ?
void insert(String key){
root=insertRec(root,key);
}
Your method does something. It obviously changes the state of the object by inserting a rec(ord?) and somehow re-evaluating what the root is. So, to test it, you should somehow be able to determine the new state, for example...
public void insert_should_create_new_record_and_set_root() {
assertThat( myObject.getRec( originalRoot) ).isNull();
Object originalRoot = myObject.getRoot();
myObject.insert("xyz");
assertThat( myObject.getRec( originalRoot) ).isEqualTo( "xyz"); // using AssertJ style here
assertThat( myObject.getRoot().value() ).isNotEqualTo( originalRoot );
}
If, on the other hand, you have no way to check the state from the outside, then you'll have a problem. But somehow your class has to communicate to the outside, hasn't it? If you really think that you cannot check the new state, then you'll have to provide more code of this class, as this answer is, of course, very general (which means "guessing", here).

How to set multiple links in RichEditBox without AccessViolationException

Essentially my problem is that I receive AccessViolationException when I try to programmatically apply more than 2 links to an ITextDocument, if a user has edited the content. I've put together a simple demo app, based on the windows phone (8.1) Blank App template.
I add to the main page:
<StackPanel Margin="19,0,0,0">
<Button
Content="Apply Links"
Click="Button_Click"
/>
<RichEditBox
x:Name="RtfBox"
Height="300"
Loaded="RtfBox_Loaded"
Margin="0,0,19,0"
TextWrapping="Wrap"
/>
</StackPanel>
And to the code behind for the same page I add (using statements not included):
private void RtfBox_Loaded(object sender, RoutedEventArgs e)
{
//RtfBox.Document.SetText(TextSetOptions.None, "Links to demo, example, test. More links to demo, demo, example, test and test.");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var pages = new Dictionary<Guid, string> { { Guid.NewGuid(), "demo" }, { Guid.NewGuid(), "example" }, { Guid.NewGuid(), "test" } };
// NOTE: Avoid performance implications of many small updates
RtfBox.Document.BatchDisplayUpdates();
ITextRange range;
foreach (var page in pages)
{
var link = string.Format("\"richtea.demo://pages/{0}\"", page.Key);
var skip = 0;
while ((range = RtfBox.Document.GetRange(skip, TextConstants.MaxUnitCount)).FindText(page.Value, TextConstants.MaxUnitCount, FindOptions.None) != 0)
{
if (range.Link == "")
{
// TODO: Stop this throw exceptions
System.Diagnostics.Debug.WriteLine("Setting text at position {0} to link: '{1}'.", range.StartPosition, link);
range.Link = link;
}
skip = range.EndPosition;
}
}
RtfBox.Document.ApplyDisplayUpdates();
}
If you start this up and type something like "A link to the demo page" and click the button, it becomes a link correctly. You can keep putting the same text and clicking the button and it continues to work.
However if you put in three or more (for some reason for me it's always 3 or more) of the words demo, example or test (my keywords) and hit the button, it errors on an AccessViolationException on setting range.Link = link. It's worth noting if you check while debugging, the range.Link property has actually been set.
More interestingly, if you uncomment RtfBox_Loaded's contents, and run the app and click the button right away, it handles it fine. So it seems to relate to the selection having been set on the RichEditBox? I've tried disabling the control before applying the links, but that's not helped me.
Some other things which have made it harder for me to diagnose the issue here include:
It seems to work more often if I'm debugging line by line, so might be timing related too
I can't use the ITextDocument not on the UI thread it seems (the COM object fails to cast) so while it seems async might be a better approach, I haven't succeeded at it here.
Also for the record, the reason I'm attempting to do all the updates on mass, rather than as the user types them is that I don't want to deal with the cleanup when notes are renamed or deleted, and I don't really want those links in at edit time or saved, but I could live with the later.
This solution was posted on the MSDN forums by Eric Fleck and worked for me:
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.StartPosition;
range.Link = link;
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.EndPosition;
It seemed that it's important to do it around each link being set, because unless I'm very much mistaken I tried this before updating all my links and it didn't help.
I'm not yet using the ability to restore the selection to it's original location, but I might want to in the future, so I made this little utility class. Also so that I can wrap places like these in a using() block for a bit of syntactic sugar.
public static class ITextDocumentExtensions
{
public static IDisposable SuppressSelection(this ITextDocument document)
{
var start = document.Selection.StartPosition;
var end = document.Selection.EndPosition;
var disposable = new ActionDisposable(() => document.Selection.SetRange(start, end));
document.Selection.SetRange(0, 0);
return disposable;
}
private sealed class ActionDisposable : IDisposable
{
private readonly Action dispose;
public ActionDisposable(Action dispose)
{
this.dispose = dispose;
}
public void Dispose()
{
dispose();
}
}
}
Which allows me to write
using (RtfBox.Document.SuppressSelection())
{
range.Link = link;
}

How to get on keyPressed in a JPanel CTRL+m?

I'm trying to implement a JPopupMenu over a text editor component. It should be activated on CTRL+m. Can I do that inside
#Override
public void keyPressed(KeyEvent arg0) {
}
and if yes, how? Because if I try
if(arg0.isControlDown()&&arg0.getKeyChar()=='m')
it doesn't work.
At first I thought it was something to do with CTRL+M being the same thing as a carriage-return/line feed, but that wasn't true. Try:
if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_M) {
System.out.println("pressed");
menu.setVisible(true);
}
I couldn't get it to work using chars with e.getKeyChar() either, but the getKeyCode() works for me. Great, it works. But I'm the type that has to know why. So I found this:
KEY_PRESSED and KEY_RELEASED events
are not intended for reporting of
character input. Therefore, the values
returned by this method are guaranteed
to be meaningful only for KEY_TYPED
events

ActionScript: Any short hand tip to reduce the verbosity of the following code?

I am very familiar with JavaScript and am now having a play with Flex for the first time. Obviously it's a strange felling as JavaScript and ActionScript are as they would say here in Southeast Asia "same same but different". The one thing that's getting to me (as with all static languages) is the verbosity. Are there any shorthand tricks that can slim down the following common code:
package com.mate.extensions {
public class HTTPResponse
{
public var data:String;
public var responseURL:String;
public var responseHeaders:Array:
public var status:Number;
public function HTTPResponse(data:String, responseURL:String, responseHeaders:Array, status:Number):void {
this.data = data;
this.responseURL = responseURL;
this.responseHeaders = responseHeaders;
this.status = status;
}
}
}
I guess it's a matter of what you're used to; I came to AS3 from Java, and to me, that code looks perfectly reasonable. :)
Honestly, I don't think you can trim this down substantially without taking a big hit in either readability or functionality. (Of course, now that I've said that, I look forward to somebody smarter than me proving me wrong.) In fact, it may actually be too terse; making your internal fields publicly accessible is generally considered bad form and an invitation to headaches down the road. Though one of the lovely things about AS3 is that because of how getters and setters are handled, you can switch from public fields to accessor-controlled private fields without needing to make any changes to code that uses this object.
If your concern is verbosity versus coding standards, you could throw the whole HTTPResponse class away and replace it with an Object.
var httpResponse:Object = { data: data, responseURL: responseURL, responseHeaders: responseHeaders, status: status };
But in that case you would miss the compile time types checking and code reusability.
The great thing with ActionScript is that it's same same & different.

How to think "Tell, don't ask" in this simple example?

How would you adhere to the "Tell, don't ask" principle (henceforth "the principle") in the following simple scenario? In a Tetris game, I have Board, BlockGrid and Piece classes relevant to the following example:
public class Board
{
private var fallingPiece:Piece;
private var blockGrid:BlockGrid;
...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
}
Once fallingPiece is placed in the bottom row of BlockGrid, it should no longer be the "fallingPiece". Am I right in that I'm not violating the principle with the following?
if(blockGrid.getPiecePosition(piece).y == 0)
{
fallingPiece = null;
}
But is that really different from this, which I think clearly violates the principle?
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
if(blockGrid.getPiecePosition(piece).y > 0)
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
else
{
fallingPiece = null;
}
}
I'm not assuming that I've designed these class relationships in the proper way to work with the principle. Please advice on an alternate design if that's what I'm missing.
EDIT, Proposed solution:
I went with the answers proposing "command feedback" via events. Board tells BlockGrid to move a piece. BlockGrid's movePiece method dispatches MOVED_TO or MOVE_FAILED events depending on the result, which Board can listen to and use to determine whether a piece has stopped falling. Please don't hesitate to provide feedback on this solution.
public class Board
{
...
public function Board()
{
...
blockGrid.addEventListener(PieceMoveEvent.MOVE_FAILED, onPieceMoveFailed);
...
}
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
public function onPieceMoveFailed(event:MovePieceEvent):void
{
if(event.instance == currentlyFallingPiece && event.fromPosition.y != event.toPosition.y)
{
currentlyFallingPiece = null;
}
}
I think, to better follow the Tell, Don't Ask principle, you should have blockGrid notifying your Board class when fallingPiece has reaches it's resting point. In both scenarios above, you are asking blockGrid if the piece's position.y == 0 in order to determine whether or not fallingPiece should be null. Instead, you want blockGrid to tell the Board class that fallingPiece.y has hit 0.
What you are looking for is Event driven programming. You need a Listener interface with a method called .event() and an Event interface to represent the events. Objects will register with other objects ( callbacks ) to the Listener interface.
when you create a Piece and Board they should implement the Listener interface. Then you can set the Board with registerListener(board); Then when things happen inside Piece it will loop thru all the registered listeners and call .event(event) on each. Same with the Board, call board.registerListener(piece) each time you create a new piece, as it decides things are happening it can tell all the registered listeners what has happened. Then you can tell a piece it is no longer falling by the Board object deciding this. Here is the obligitory Wikipedia entry.
I would expect a class representing each shape (without position information), a controller containing a shape, position and orientation, and another class representing the current resulting grid of "landed" shapes. The landed-grid would have a
testLanded(shape, shapePosition, orientation)
method which would be called before/after each move operation to decide if the shape is to join the landed grid or should move and stay as the falling piece.
I'm going on the idea of not giving data to objects that shouldn't really own that data - but I've never implemented Tetris...
You may need to rethink your design. Does Board really need to track the falling piece or should that belong to BlockGrid? Iron out who owns what behavior.
Keep position information on your Piece class and possibly have your Piece class hold an instance of the BlockGrid.
You can then try something like this in your Board class...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.moveFallingPiece(xDirection, yDirection);
}
Then in BlockGrid's moveFallingPiece method...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
fallingPiece.move(xDirection, yDirection);
}
In Piece's move method, add your logic...
public function move(xDirection:int, yDirection:int):void
{
setPosition(xDirection, yDirection);
if (getPosition().y <= 0)
{
blockGrid.setFallingPiece(null);
// this can bubble up to Board if need be
}
}
Not sure of all the power of AS3, but it would make sense to use abstractions here. (i.e., have your Piece class depend on ITrackFallingPieces instead of BlockGrid and have BlockGrid implement ITrackFallingPieces).
Good luck!