Is there a convention or guideline for mutable state in a Blazor component? - razor

Coming from React JS, I wonder if Blazor has the concepts of State and Property. See the code below:
<div>#field</div>
<button #onclick=#(() => field = Random.Shared.Next())>Change field</button>
<div>#Prop</div>
<button #onclick=#(() => Prop = Random.Shared.Next())>Change prop</button>
#code {
private int field;
[Parameter]
public int Prop { get; set; }
}
There is absolutely no difference between field and Prop, except that you can set Prop from the parent's template. I haven't been able to create a property that cannot be updated within the component, since the public setter is required.
It seems to be up to the team to decide whether it makes sense to update a property within the component or not.
Is there a convention/best practice/guideline about that?

Is there a convention/best practice/guideline about that?
Yes: do no do that.
Most 'official' is in the docs here:
Our general guidance is not to create components that directly write to their own parameters after the component is rendered for the first time.
and here:
Generally, avoid creating components that write directly to their own component parameters. ...
but that is repeated and explained in many places.

Related

My editor templates for an empty list is not rendering

I have a custom editor in my EditorTemplates folder for a IList<PersonRelations>. The Editor has this model:
#model IList<PersonRelation>
and in my entity is as this:
public IList<PersonRelation> Relations { get; set; }
this is how I called it in my view:
<div class="editor-field">
#Html.EditorFor(model => model.Relations)
</div>
and it's rendering the model if Relations is null.
But.. I want to declare my property in this way
private IList<PersonRelation> _relations;
public IList<PersonRelation> Relations
{
get { return _relations ?? (_relations = new List<PersonRelation>()); }
set { _relations = value; }
}
To avoid null references exceptions.
The thing is when the List is not null and has no elements, the editor is not being displayed at all.
In my editor I iterate through the elements but also I render another controls outside the loop, and I can't see any elements.
I'm missing something?
Solved.
When I changed the property, I forgot to decorate it with [UIHint("PersonRelations")]
which was in the original form of the property (my custom editor's file name is "PersonRelations.cshtml")
This is needed due it seems that the engine is not able to infer the editor for a collection, even when you have one, so you explicitly have to tell which one you want to use.

Robotlegs wiring up dependencies that belong to a base class

I'm using robot legs, I've got a bunch of ServiceResponses that extends a base class and have a dependency on a Parser, IParser. I need to wire in a parser specific to the subclass. Here's an example:
ModuleConfigResponse extends SimpleServiceResponse and implements IServiceResponse.
The initial part is easy to wire in the context, here's an example:
injector.mapClass(IServiceResponse, ModuleConfigResponse);
injector.mapClass(IServiceResponse, SimpleServiceResponse, "roomconfig");
..etc
Each Response uses a parser that is used by the baseclass:
injector.mapValue(IParser, ModuleConfigParser, "moduleconfig");
injector.mapValue(IParser, RoomConfigParser, "roomconfig");
The question is how to tie these together. The base class could have:
[Inject]
public var parser : IParser
But I can't define the type ahead of time. Im wondering if there a nice way of wiring this in the context. For the moment I've decided to wire this up by instanciating responses in a ResponseFactory instead so that I pay pass the parser manually in the constructor.
injector.mapValue(IParser, ModuleConfigParser, "moduleconfig");
I realised that not everything can be mapped in the context, RL trapped me into this way of thinking. But I've realised that its far better to map a factory to produce these objects which have very specific dependencies, than littler the codebase with marker interfaces or strings :)
one solution is to have the following in your base class:
protected var _parser : IParser
Then for instance in ModuleConfigResponse
[Inject(name='moduleconfig')]
public function set parser( value : IParser ) : void{
_parser = value;
}
But TBH, using named injections is STRONGLY discouraged, you might as well use a marker interface:
public interface IModuleConfigParser extends IParser{}
the base class stays the same, but ModuleConfigResponse would then use:
[Inject]
public function set parser( value : IModuleConfigParser ) : void{
_parser = value;
}

Override virtual methods in partial classes that are generated

In my LINQ generate class, I have this method:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Id",
AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY",
IsPrimaryKey=true, IsDbGenerated=true)]
public int Id
{
get
{
return this._Id;
}
set
{
if ((this._Id != value))
{
this.OnIdChanging(value);
this.SendPropertyChanging();
this._Id = value;
this.SendPropertyChanged("Id");
this.OnIdChanged();
}
}
}
In my coded partial class, I extend from a base class. The base class defines:
public virtual int Id { get; set; }
The concept is that I can add the Equals and Hashcode at the base class level, as well as some other functionality at the base class level. The problem is that the generated classes (from LINQ-to-SQL) do not get an override keyword so it doesnt work. If it had override I would be all set.
Please suggest on how to complete this.
You could make the base class abstract, and then the Id property becomes
public abstract int Id { get; set; }
The generated code will implement that abstract property.
A partial class is different from overriding a class. With a partial class you're just saying. Ok, i have 1 class but i have splitted the source up over multiple files (mainly for maintainable reasons like splitting the auto generated code from your own code). The C# compiler just merges each part of a partial class together and threats it as 1 class. Ofcourse overriding a class means you create a new class which takes on the characteristics of the base class. That is very different.
Now it's possible but not relatively easy to direct EF of how to generate your code (assuming you are using EF). One option you can do though is to change your base class not to work with the Property Id but a more recognizable (and specifix?) name like 'CompareIdentifier'. With that you can override CompareIdentifier in your derived class for returning the auto generated ID. And ofcourse do all comparison work against CompareIdentifier
I would have created a wrapper class around this.

How can I create a subclass that takes in different parameters for the same function name?

So I have made this simple interface:
package{
public interface GraphADT{
function addNode(newNode:Node):Boolean;
}
}
I have also created a simple class Graph:
package{
public class Graph implements GraphADT{
protected var nodes:LinkedList;
public function Graph(){
nodes = new LinkedList();
}
public function addNode (newNode:Node):Boolean{
return nodes.add(newNode);
}
}
last but not least I have created another simple class AdjacancyListGraph:
package{
public class AdjacancyListGraph extends Graph{
public function AdjacancyListGraph(){
super();
}
override public function addNode(newNode:AwareNode):Boolean{
return nodes.add(newNode);
}
}
Having this setup here is giving me errors, namely:
1144: Interface method addNode in namespace GraphADT is implemented with an incompatible signature in class AdjacancyListGraph.
Upon closer inspection it was apparent that AS3 doesn't like the different parameter types from the different Graph classes newNode:Node from Graph , and newNode:AwareNode from AdjacancyListGraph
However I don't understand why that would be a problem since AwareNode is a subClass of Node.
Is there any way I can make my code work, while keeping the integrity of the code?
Simple answer:
If you don't really, really need your 'addNode()' function to accept only an AwareNode, you can just change the parameter type to Node. Since AwareNode extends Node, you can pass in an AwareNode without problems. You could check for type correctness within the function body :
subclass... {
override public function addNode (node:Node ) : Boolean {
if (node is AwareNode) return nodes.add(node);
return false;
}
}
Longer answer:
I agree with #32bitkid that your are getting an error, because the parameter type defined for addNode() in your interface differs from the type in your subclass.
However, the main problem at hand is that ActionScript generally does not allow function overloading (having more than one method of the same name, but with different parameters or return values), because each function is treated like a generic class member - the same way a variable is. You might call a function like this:
myClass.addNode (node);
but you might also call it like this:
myClass["addNode"](node);
Each member is stored by name - and you can always use that name to access it. Unfortunately, this means that you are only allowed to use each function name once within a class, regardless of how many parameters of which type it takes - nothing comes without a price: You gain flexibility in one regard, you lose some comfort in another.
Hence, you are only allowed to override methods with the exact same signature - it's a way to make you stick to what you decided upon when you wrote the base class. While you could obviously argue that this is a bad idea, and that it makes more sense to use overloading or allow different signatures in subclasses, there are some advantages to the way that AS handles functions, which will eventually help you solve your problem: You can use a type-checking function, or even pass one on as a parameter!
Consider this:
class... {
protected function check (node:Node) : Boolean {
return node is Node;
}
public function addNode (node:Node) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
In this example, you could override check (node:Node):
subclass... {
override protected function check (node:Node) : Boolean {
return node is AwareNode;
}
}
and achieve the exact same effect you desired, without breaking the interface contract - except, in your example, the compiler would throw an error if you passed in the wrong type, while in this one, the mistake would only be visible at runtime (a false return value).
You can also make this even more dynamic:
class... {
public function addNode (node:Node, check : Function ) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
Note that this addNode function accepts a Function as a parameter, and that we call that function instead of a class method:
var f:Function = function (node:Node) : Boolean {
return node is AwareNode;
}
addNode (node, f);
This would allow you to become very flexible with your implementation - you can even do plausibility checks in the anonymous function, such as verifying the node's content. And you wouldn't even have to extend your class, unless you were going to add other functionality than just type correctness.
Having an interface will also allow you to create implementations that don't inherit from the original base class - you can write a whole different class hierarchy, it only has to implement the interface, and all your previous code will remain valid.
I guess the question is really this: What are you trying to accomplish?
As to why you are getting an error, consider this:
public class AnotherNode extends Node { }
and then:
var alGraph:AdjacancyListGraph = new AdjacancyListGraph();
alGraph.addNode(new AnotherNode());
// Wont work. AnotherNode isn't compatable with the signature
// for addNode(node:AwareNode)
// but what about the contract?
var igraphADT:GraphADT = GraphADT(alGraph);
igraphADT.addNode(new AnotherNode()); // WTF?
According to the interface this should be fine. But your implemenation says otherwise, your implemenation says that it will only accept a AwareNode. There is an obvious mismatch. If you are going to have an interface, a contract that your object should follow, then you might as well follow it. Otherwise, whats the point of the interface in the first place.
I submit that architecture messed up somewhere if you are trying to do this. Even if the language were to support it, I would say that its a "Bad Idea™"
There's an easier way, then suggested above, but less safe:
public class Parent {
public function get foo():Function { return this._foo; }
protected var _foo:Function = function(node:Node):void { ... }}
public class Child extends Parent {
public function Child() {
super();
this._foo = function(node:AnotherNode):void { ... }}}
Of course _foo needs not be declared in place, the syntax used is for shortness and demonstration purposes only.
You will loose the ability of the compiler to check types, but the runtime type matching will still apply.
Yet another way to go about it - don't declare methods in the classes they specialize on, rather make them static, then you will not inherit them automatically:
public class Parent {
public static function foo(parent:Parent, node:Node):Function { ... }}
public class Child extends Parent {
public static function foo(parent:Child, node:Node):Function { ... }}
Note that in second case protected fields are accessible inside the static method, so you can achieve certain encapsulation. Besides, if you have a lot of Parent or Child instances, you will save on individual instance memory footprint (as static methods therefore static there exists only one copy of them, but instance methods would be copied for each instance). The disadvantage is that you won't be able to use interfaces (can be actually an improvement... depends on your personal preferences).

Swing beans binding: how do I notify the target that the model has changed?

I have a swing app with a text box bound to a property on my model (this is a READ_WRITE AutoBinding). The model also has an isDirty property that I want to bind to a button's enabled property.
How do I properly notify the binding when I change the state of isDirty.
Here is my binding code:
BeanProperty<PaChannelConfig, Boolean> paChannelConfigBeanProperty_1 =
BeanProperty.create("dirty");
BeanProperty<JButton, Boolean> jButtonBeanProperty =
BeanProperty.create("enabled");
AutoBinding<PaChannelConfig, Boolean, JButton, Boolean> autoBinding_2 =
Bindings.createAutoBinding(
UpdateStrategy.READ,
model,
paChannelConfigBeanProperty_1,
btnApply, jButtonBeanProperty);
autoBinding_2.bind();
What is the proper way to add this notification?
Basically, the model should have the methods
addPropertyChangeListener(PropertyChangeListener)
removePropertyChangeListener(PropertyChangeListener)
firePropertyChange(PropertyChangeEvent)
look at the class PropertyChangeSupport, that class have implementations of the methods above.
In the model, the method setDirty(boolean) should be implemented like this:
public void setDirty(boolean dirty) {
boolean old = this.dirty;
this.dirty = dirty;
firePropertyChange(new PropertyChangeEvent("dirty", old, dirty));
}
hope that helps
You can use PropertyChangeSupport to easily implement support for property change notification. The documentation at the provided link has an example of how to set it up and use it.