How to pass object to child component via Inputs() but never update input when it changes in parent - node.js

I'm passing an object from a parent component to a child component via Inputs(). I know because I'm passing an object and not a primitive type it's passing a reference to the object. Thus when the object changes in the parent I see it being reflected in the child.
What is the optimal way to pass an object via Inputs() that does NOT update the child component when it changes in the parent?

You need to have two properties that you use. One that you modify and a second that is passed to the child component but is a clone of the original.
#Component({..})
export class MyComponent implements OnInit {
// the original object value
public value: any;
// a value used by child components
public forChild: any;
public OnInit() {
// use deconstruction to make a copy
this.forChild = {...this.value};
// use assign to make a copy
this.forChild = Object.assign({}, this.value);
// use JSON to make a deep copy
this.forChild = JSON.parse(JSON.stringify(this.value));
}
}

As you mentioned:
When we pass objects using #Input(), it would be passed as a reference,
and When we pass primitive types, it would be passed as a value.
So i think one solution is to convert your object to string, and then pass it using #Input(). Later you can decode this stringifyed object to a object if you need.

Related

Node.js | Override Setter

I have a class instance (in my case the class is URL), called req_url. URL has a property that has a setter for one of its properties (search) that is implemented in a way that is problematic for me (doesn't just set the given value but does something to it first).
How can I override that setter without creating a class that inherits from URL (and then create a different setter)?
defineProperty doesn't work since it works at the Object level. I want to to do it on that specific type level.
Whenever you have an instance whose setter you want to bypass, calling Object.defineProperty on the instance to set the property does work:
class Foo {
set prop(arg) {
console.log('setter invoked');
}
}
const f = new Foo();
Object.defineProperty(f, 'prop', { value: 'val' });
console.log(f.prop);
It won't affect any object, it'll only affect objects you explicitly call Object.defineProperty with. The collisions with other objects you seem to be worried about won't occur.
Another (stranger) option would be to delete the setter on the prototype, though if the class is used elsewhere, outside of your code, it could cause problems:
class Foo {
set prop(arg) {
console.log('setter invoked');
}
}
delete Foo.prototype.prop;
const f = new Foo();
f.prop = 'val';
console.log(f.prop);

How do you access private methods or attributes from outside the type they belong to?

In some rare cases where this would actually be acceptable, like in unit tests, you may want to get or set the value of a private attribute, or call a private method of a type where it shouldn't be possible. Is it really impossible? If not, how can you do it?
There are two ways you can access a private method of a type, and one way to get private attributes. All require meta-programming except for the first way to invoke private methods, whose explanation still involves meta-programming anyway.
As an example, we will be implementing a Hidden class that hides a value using a private attribute, and a Password class that uses Hidden to store a password. Do not copy this example to your own code. This is not how you would reasonably handle passwords; this is solely for example's sake.
Calling private methods
Trusting other classes
Metamodel::Trusting is the meta-role that implements the behaviour needed for higher-order workings (types of types, or kinds, referred to from hereon out as HOWs) to be able to trust other types. Metamodel::ClassHOW (classes, and by extension, grammars) is the only HOW that's builtin to Rakudo that does this role.
trusts is a keyword that can be used from within packages to permit another package to call its private methods (this does not include private attributes). For example, a rough implementation of a password container class could look like this using trusts:
class Password { ... }
class Hidden {
trusts Password;
has $!value;
submethod BUILD(Hidden:D: :$!value) {}
method new(Hidden:_: $value) {
self.bless: :$value
}
method !dump(Hidden:D: --> Str:D) {
$!value.perl
}
}
class Password {
has Hidden:_ $!value;
submethod BUILD(Password:D: Hidden:D :$!value) {}
method new(Password:_: Str:D $password) {
my Hidden:D $value .= new: $password;
self.bless: :$value
}
method !dump(Password:D: --> Str:D) {
qc:to/END/;
{self.^name}:
$!value: {$!value!Hidden::dump}
END
}
method say(Password:D: --> Nil) {
say self!dump;
}
}
my Password $insecure .= new: 'qwerty';
$insecure.say;
# OUTPUT:
# Password:
# $!value: "qwerty"
#
Using the ^find_private_method meta-method
Metamodel::PrivateMethodContainer is a meta-role that implements the behaviour for HOWs that should be able to contain private methods. Metamodel::MethodContainer and Metamodel::MultiMethodContainer are the other meta-roles that implement the behaviour for methods, but those won't be discussed here. Metamodel::ClassHOW (classes, and by extension, grammars), Metamodel::ParametricRoleHOW and Metamodel::ConcreteRoleHOW (roles), and Metamodel::EnumHOW (enums) are the HOWs builtin to Rakudo that do this role. One of Metamodel::PrivateMethodContainer's methods is find_private_method, which takes an object and a method name as parameters and either returns Mu when none is found, or the Method instance representing the method you're looking up.
The password example can be rewritten not to use the trusts keyword by removing the line that makes Hidden trust Password and changing Password!dump to this:
method !dump(Password:D: --> Str:D) {
my Method:D $dump = $!value.^find_private_method: 'dump';
qc:to/END/;
{self.^name}:
$!value: {$dump($!value)}
END
}
Getting and setting private attributes
Metamodel::AttributeContainer is the meta-role that implements the behaviour for types that should contain attributes. Unlike with methods, this is the only meta-role needed to handle all types of attributes. Of the HOWs builtin to Rakudo, Metamodel::ClassHOW (classes, and by extension, grammars), Metamodel::ParametricRoleHOW and Metamodel::ConcreteRoleHOW (roles), Metamodel::EnumHOW (enums), and Metamodel::DefiniteHOW (used internally as the value self is bound to in accessor methods for public attributes) do this role.
One of the meta-methods Metamodel::AttributeContainer adds to a HOW is get_attribute_for_usage, which given an object and an attribute name, throws if no attribute is found, otherwise returns the Attribute instance representing the attribute you're looking up.
Attribute is how attributes are stored internally by Rakudo. The two methods of Attribute we care about here are get_value, which takes an object that contains the Attribute instance and returns its value, and set_value, which takes an object that contains the Attribute instance and a value, and sets its value.
The password example can be rewritten so Hidden doesn't implement a dump private method like so:
class Hidden {
has $!value;
submethod BUILD(Hidden:D: :$!value) {}
method new(Hidden:_: $value) {
self.bless: :$value;
}
}
class Password {
has Hidden:_ $!value;
submethod BUILD(Password:D: Hidden:D :$!value) {}
method new(Password:_: Str:D $password) {
my Hidden:D $value .= new: $password;
self.bless: :$value
}
method !dump(Password:D: --> Str:D) {
my Attribute:D $value-attr = $!value.^get_attribute_for_usage: '$!value';
my Str:D $password = $value-attr.get_value: $!value;
qc:to/END/;
{self.^name}:
$!value: {$password.perl}
END
}
method say(Password:D: --> Nil) {
say self!dump;
}
}
my Password:D $secure .= new: 'APrettyLongPhrase,DifficultToCrack';
$secure.say;
# OUTPUT:
# Password:
# $!value: "APrettyLongPhrase,DifficultToCrack"
#
F.A.Q.
What does { ... } do?
This stubs a package, allowing you to declare it before you actually define it.
What does qc:to/END/ do?
You've probably seen q:to/END/ before, which allows you to write a multiline string. Adding c before :to allows closures to be embedded in the string.
Why are grammars classes by extension?
Grammars use Metamodel::GrammarHOW, which is a subclass of Metamodel::ClassHOW.
You say ^find_private_method and ^get_attribute_for_usage take an object as their first parameter, but you omit it in the example. Why?
Calling a meta-method on an object passes itself as the first parameter implicitly. If we were calling them directly on the object's HOW, we would be passing the object as the first parameter.

How to manage methods\variables caller class?

in class standard class Dialog exist an Object declare (in classDeclaration)
Object caller;
In this class I'm able to get the caller class name. For example:
if (caller.name() == classStr(MyCallerClass) )
{
// manage-pass variable in caller class
}
If I catch in the IF, I want to pass a parameter in parm method in to MyCallerClass.
How I can pass a simple parameter? For example:
if (caller.name() == classStr(MyCallerClass) )
{
// MyCallerClass.myParmMethod(parameter);
}
Thanks.
Just call the method:
if (caller.name() == classStr(MyCallerClass))
caller.myParmMethod('abc');
As caller is of type Object the compiler accepts any method name, it uses duck typing.
A run time error happens if caller does not have the method.
That said, you should not change the standard Dialog class.
You might extend the class, though this is unlikely to be the right thing.
What you should do depends on information you do not give.
The correct & safe way is:
MyCallerClass myCalss;
if (caller && classidget(caller) == classnum(MyCallerClass))
{
myClass = caller;
myClass.myParmMethod('abc');
}
See examples in form.init methods.

Polymer camelCase attributes

I'm writing a wrapper around a js library with Polymer components. Basically, I need to be able to assign attributes to a component, and forward them to an instance of a js object.
The problem is that Polymer (or webcomponents in general?) forces attribute names to be lowercase.
Declaring the element
<some-element fooBar="baz"></some-element>
Generic change listener
attributeChanged: function(attrName, oldVal, newVal){
// attrName -> foobar, which is not a member of someInstance
this.someInstance[attrName] = newVal;
}
Is there some way to get the camel-cased name? Maybe I can create a hash from the publish object on the prototype... but how do I reference that?
Aha! publish is actually available on the component instance! This allows me to grab the names and make a map from lowercase to camelcase.
var map = {};
Object.keys(this.publish).forEach(function(key){
map[key.toLowerCase()] = key;
});

Cannot make a generic fake for a class using object

Cannot make a generic fake for a class using object like
Fakes.ShimDataServiceRepository<object>.AllInstances.GetEntitiesExpressionOfFuncOfT0Boolean = (instance, filter) =>
{
return null;
}
The call goes to actual code implementation.
But when we specify the object type, it is working
Fakes.ShimDataServiceRepository<Customer>.AllInstances.GetEntitiesExpressionOfFuncOfT0Boolean = (instance, filter) =>
{
return null;
}
But i need a general single fake for all objects so no need to repeat the code for each objects.
My question is why the fake with <object> is not working?. As it is the parent of all the classes.
Please any one help me :(
My question is why the fake with is not working?. As it is the parent of all the classes.
Object is the parent of all classes, but DataServiceRepository<object> is not the parent of DataServiceRepository<Customer>.
A generic class with different concrete types is no longer "the same class". The two types don't share statics or fakes.

Resources