Is it possible to add dynamically named properties to JavaScript object?
Yes.
var data = { 'PropertyA': 1, 'PropertyB': 2, 'PropertyC': 3};
data["PropertyD"] = 4;
// dialog box with 4 in italert(data.PropertyD);alert(data["PropertyD"]);
Dynamically Add C# Properties at Runtime
Have you taken a look at ExpandoObject?
see: https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject
From MSDN:
The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember instead of more complex syntax like sampleObject.GetAttribute("sampleMember").
Allowing you to do cool things like:
dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
{
Console.WriteLine(msg);
};
dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);
Based on your actual code you may be more interested in:
public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
return new MyDynObject(properties);
}
public sealed class MyDynObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;
public MyDynObject(Dictionary<string, object> properties)
{
_properties = properties;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
_properties[binder.Name] = value;
return true;
}
else
{
return false;
}
}
}
That way you just need:
var dyn = GetDynamicObject(new Dictionary<string, object>()
{
{"prop1", 12},
});
Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;
Deriving from DynamicObject allows you to come up with your own strategy for handling these dynamic member requests, beware there be monsters here: the compiler will not be able to verify a lot of your dynamic calls and you won't get intellisense, so just keep that in mind.
How to create new property dynamically
There are two methods to doing it.
One, you can directly create property dynamically from outside the class:
class Foo{
}
$foo = new Foo();
$foo->hello = 'Something';
Or if you wish to create property through your createProperty
method:
class Foo{
public function createProperty($name, $value){
$this->{$name} = $value;
}
}
$foo = new Foo();
$foo->createProperty('hello', 'something');
C# dynamically set property
objName.GetType().GetProperty("nameOfProperty").SetValue(objName, objValue, null)
How to create an object with dynamic property names
In your code fruits.props[i] = 'Juice';
would try to set the 0th index value of props
property where the property is undefined
and causing the error.
Use bracket notation for assigning object property using a string.
var fruits = {};
var props = ['orange', 'apple', 'banana'];
for (var i = 0; i < props.length; i++) { fruits[props[i]] = 'Juice'; //----^^^^^^^^^^-----}
console.log(fruits);
How do I dynamically assign properties to an object in TypeScript?
Index types
It is possible to denote obj
as any
, but that defeats the whole purpose of using typescript. obj = {}
implies obj
is an Object
. Marking it as any
makes no sense. To accomplish the desired consistency an interface could be defined as follows.
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
OR to make it compact:
var obj: {[k: string]: any} = {};
LooseObject
can accept fields with any string as key and any
type as value.
obj.prop = "value";
obj.prop2 = 88;
The real elegance of this solution is that you can include typesafe fields in the interface.
interface MyType {
typesafeProp1?: number,
requiredProp1: string,
[key: string]: any
}
var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number
obj.prop = "value";
obj.prop2 = 88;
Record<Keys,Type>
utility type
Update (August 2020): @transang brought this up in comments
Record<Keys,Type>
is a Utility type in typescript. It is a much cleaner alternative for key-value pairs where property-names are not known.
It's worth noting thatRecord<Keys,Type>
is a named alias to{[k: Keys]: Type}
whereKeys
andType
are generics.
IMO, this makes it worth mentioning here
For comparison,
var obj: {[k: string]: any} = {};
becomes
var obj: Record<string,any> = {}
MyType
can now be defined by extending Record type
interface MyType extends Record<string,any> {
typesafeProp1?: number,
requiredProp1: string,
}
While this answers the Original question, the answer here by @GreeneCreations might give another perspective on how to approach the problem.
Create and assign a object property dynamically typescript
This happens because on your second last line: this.myHistory
is undefined
. You are trying to access the property ourHistory
of undefined
, which the compiler does not like.
You need to instantiate the property, like mentioned in the comments to your question.
One way to do it, could do it like so:
export class HistoryComponent implements OnInit, OnDestroy {
myHistory: OurHistory;
let ourHistory = [];
ourHistory = this.allHistory.fields['ourHistory'];
this.myHistory = {ourHistory: ourHistory[0]};
}
This way, we instantiate the property myHistory
with a new object:
{
ourHistory: someValue
}
C# - Adding objects dynamically (adding dynamic property names)
Rather than creating an ExpandoObject
or some other dynamic type, you could create a List<Dictionary<string, object>>
where each Dictionary<string, object>
contains the name/value pairs you want to serialize. Then serialize to JSON using Json.NET (or JavaScriptSerializer
, though that is less flexible):
var list = new List<Dictionary<string, object>>();
// Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx
list.Add(new Dictionary<string, object> { { "ID", 1 }, {"Product", "Pie"}, {"Days", 1}, {"QTY", 65} });
// Build a dictionary entry incrementally
// See https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
var dict = new Dictionary<string, object>();
dict["ID"] = 2;
dict["Product"] = "Melons";
dict["Days"] = 5;
dict["QTY"] = 12;
list.Add(dict);
Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
Console.WriteLine(new JavaScriptSerializer().Serialize(list));
The first outputs:
[
{
"ID": 1,
"Product": "Pie",
"Days": 1,
"QTY": 65
},
{
"ID": 2,
"Product": "Melons",
"Days": 5,
"QTY": 12
}
]
The second outputs the same without the indentation:
[{"ID":1,"Product":"Pie","Days":1,"QTY":65},{"ID":2,"Product":"Melons","Days":5,"QTY":12}]
Related Topics
Validating Us Phone Number with PHP/Regex
How to Access Magento User's Session from Outside Magento
Oauth Implementation in Netsuite Using PHP
How to Pass Value from One PHP Page to Another Using Session
Good Error Handling with File_Get_Contents
PHP Include Causes White Space at the Top of the Page
PHP String Interpolation Syntax
Pdo SQLite Could Not Find Driver... PHP File Not Processing
PHP Regex to Get String Inside Href Tag
Belongstomany Relationship in Laravel Across Multiple Databases
Error 1148 MySQL the Used Command Is Not Allowed with This MySQL Version
Decrypting Strings in Python That Were Encrypted with Mcrypt_Rijndael_256 in PHP
Best Way to Store Passwords in MySQL Database
Memory_Get_Peak_Usage() with "Real Usage"