Angular - call setters/getters in html - html

I have in the .ts file the following code:
set query(query: string) {
this.form.get('query').setValue(query);
}
get query() {
return this.form.controls.query;
}
I am trying to call the getter method in .html file as:
<div *ngIf="!query.valid && (query?.dirty || query?.touched)">
<div [hidden]="!query.errors.required">Query is required</div>
</div>
However, an error is thrown. The code works perfectly if I remove the setter from the .ts file.
Why does this happen?

You can do it via two ways,
Way 1:
set query(query: any) {
this.form.get('query').setValue(query);
}
get query() {
return this.form.controls.query;
}
Way 2:
set query(query: string) {
this.form.get('query').setValue(query);
}
get query(): AbstractControl {
return this.form.controls.query;
}
when you assign a value to query you are assigning it as a string see the incoming argument type in your setter. So by default angular understands it as string type. Then in your HTML, you try to access it as an object which creates a problem for angular as it expects it to be a string but used as an object.

try form.getControls['query'].setValue(myValue)
form.get('fieldName') will get value of that field ...
form.controls['fieldName'] would get the field itself .. Field control will expose get or set value methods

Although the accepted answer works and the thinking behind it make sense, I would completely avoid using any as a return type, when you know exactly what you're returning.
That just goes against the purpose of using Typescript as a language. Using any is the same as saying "accept everything and don't just interpret it as a string".
set query(query: string) {
this.form.get('query').setValue(query);
}
get query(): AbstractControl {
return this.form.controls.query;
}
Since you know you're returning an AbstractControl, I would set the return type to either AbstractControl or, if you want to be more specific, to FormControl.

Related

Specifying a property as `type: Array` doesn't seem to parse the string property value correctly

Update: Filed a bug at https://github.com/Polymer/lit-element/issues/411
I'm having trouble implementing the default and custom converter for properties given the information in the guide. With the current version (0.6.5), it says that you can assign the type Array to a property and it will automatically be parsed as JSON from the string value of the attribute, but that doesn't seem to be the case as described in the code sample.
Here's an illustration of the problem. In the console, it should report an array with three elements, yet it returns an array of one element, the string that contains the attribute value. The result of the render method also shows just one <p> element containing the single string.
<script type="module">
import { LitElement, html } from 'https://unpkg.com/#polymer/lit-element#0.6.5/lit-element.js?module';
class Histogram extends LitElement {
static get properties() {
return {
values: { type: Array }
};
}
constructor() {
super();
this.values = [];
}
render() {
console.log(Array.isArray(this.values), this.values);
return html`
<div>
The elements:
${this.values.map(item => html`<p>item: ${item}</p>`)}
</div>
`;
}
}
customElements.define('x-histogram', Histogram);
</script>
<x-histogram values="[1,2,3]"/>
I've also tried modifying the example by providing a converter, but that doesn't seem to get invoked, either. What am I doing wrong?
I had a look. The 0.6.5 updating-element.js file doesn't even have converting for array. And looking at the npm package of 0.6.5 it doesn't mention an array either.
But the master branch does map the array type, and it has it mentioned in the readme. It should work for you if you pull it and use it directly.

TypeScript: how to JSON stringify a class definition?

Say we have:
class MyClass {
myProperty: string
}
Is there any built in function or easy way to get JSON like this?:
{
"myProperty": "string"
}
EDIT: My end goal is I want to dynamically print typed class definitions to a web view, in some kind of structured object syntax like JSON. I'm trying to make a server API that will return the schema for various custom classes - for example http://myserver.com/MyClass should return MyClass's properties and their types as a JSON string or other structured representation.
Evert is correct, however a workaround can look like this
class MyClass {
myProperty: string = 'string'
}
JSON.stringify(new MyClass) // shows what you want
In other words, setting a default property value lets TS compile properties to JS
If the above solution is not acceptable, then I would suggest you parsing TS files with your classes with https://dsherret.github.io/ts-simple-ast/.
Typescript class properties exist at build-time only. They are removed from your source after compiling to .js. As such, there is no run-time way to get to the class properties.
Your code snippet compiles to:
var MyClass = /** #class */ (function () {
function MyClass() {
}
return MyClass;
}());
As you can see, the property disappeared.
Based on your update, I had this exact problem. This is how I solved it.
My JSON-based API uses json-schema across the board for type validation, and also exposes these schemas for clients to re-use.
I used an npm package to automatically convert json-schema to Typescript.
This works brilliantly.

use page as argument in Umbraco

I'm trying to pass page as argument in Umbraco . and in a helper I need some properties of the page . like Name , ...
This is my code :
var PageWeAreInheritedFrom = CurrentPage;
#ShowBanner(PageWeAreInheritedFrom);
#helper ShowBanner(dynamic pageWeRIn)
{
if (pageWeRIn.bannerIsInherited)
{
#ShowBanner(pageWeRIn.Parent)
}
else
{
//here I want to have a switch case based on pageWeRIn.Name
//but I cant have it.
}
}
This is the Error .seems the page type is different in the helper method
A switch expression or case label must be a bool, char, string,
integral, enum, or corresponding nullable type
This is caused because pageWeRIn is dynamic and C#'s switch can't work with dynamic variables. I personally don't work with dynamics in my views but only with typed models. For more information see: http://24days.in/umbraco-cms/2015/strongly-typed-vs-dynamic-content-access/
A typed implementation would look somehthing like this (not tested):
#ShowBanner(Mode.Content);
#helper ShowBanner(IPublishedContent pageWeRIn)
{
if (pageWeRIn.GetPropertyValue<bool>("bannerIsInherited"))
{
#ShowBanner(pageWeRIn.Parent)
}
else
{
//use all the switches you want on pageWeRIn.Name
}
}
Another way to do it without changing the whole code would be to introduce a new variable that's typed (as Jannik explained in his comment) and then use a switch
string nodeName = pageWeRIn.Name
switch(nodeName){
// whatever
}

Return an unset value in value converter

Using a value converter in WPF, you can return something like DependecyProperty.UnsetValue or Binding.DoNothing as special values to say leave the binding alone. Is there a similar mechanism in MVVMCross?
To be more specific about what I'm trying to do, is I have a view model property that is a three-state enum that I need to bind to 3 binary controls. So I thought I could bind each of the controls to a MyEnum -> bool converter that will have a conversion parameter set to the value of the converter and in the Convert method it will return true if the MyEnum state is equal to the parameter and false otherwise. So far so good. But I want this binding to be two-way, so I need to convert back. My convert back works something like this:
protected override MyEnum ConvertBack(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter is MyEnum)
{
if (value)
{
return (MyEnum)parameter; // this is fine
}
else
{
return ???
}
}
return base.ConvertBack(value, targetType, parameter, culture);
}
Basically, what I want to be able to do is say, if the state of my control is true update the bound property on my view model to be the same as the parameter, if not, leave the view model property alone.
Maybe this is the problem with using the strongly typed value converters?
If anybody else encounters a similar problem, in addition to Stuart's suggestions, this is what I actually ended up doing.
In the View Model
private MyEnum _selectedValue = MyEnum.SomeValue;
public MyEnum ? SelectedValue
{
get
{
return _selectedTab;
}
set
{
if (value.HasValue)
{
_selectedTab = value.Value;
RaisePropertyChanged(() => SelectedTab);
}
}
}
Then in my converter (now a MvxValueConverter<MyEnum?, bool>):
protected override MyEnum? ConvertBack(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter is MyEnum) // this is just a sanity check
{
if (value)
{
return (MyEnum)parameter;
}
else
{
return null
}
}
return base.ConvertBack(value, targetType, parameter, culture);
}
It's not a general solution, but it fits my immediate need.
Update: UnsetValue is now available in mvvmcross - so this answer is no longer required.
Binding.DoNothing, DependencyProperty.UnsetValue or equivalent are currently not implemented in the MvvmCross binding system, and I don't believe there are any feature or pull requests currently open on this.
I'm afraid I don't really understand your example - the 'conversion parameter set to the value of the converter' and the if (parameter is MyEnum) snippet rather threw me - as far as I know, the parameter in windows xaml binding is a constant so I don't quite understand this example. Sorry if I've misunderstood.
Regardless, some possible approaches that might be used to assist with getting this functionality up and running in your mvx app are:
You could throw an exception from the ValueConverter:
For the Convert direction, the binding FallbackValue is used if a ValueConverter fails (throws an exception)
For the ConvertBack direction, the binding does nothing if an exception is thrown (although this would unfortunately generate some trace "error" output each time)
You could implement a custom binding for your control - something which only fires change updates when the change is one you are interested in (some custom bindings are introduced in N=28 in http://mvvmcross.wordpress.com which creates bindings like BinaryEditFooTargetBinding.cs - it would be straight-forward to customise/filter the TargetOnMyCountChanged behaviour in that class)
You could implement a custom binary control - which only fires change updates when the change is one you are interested in (for various platforms, some custom controls are introduced in N=18 to N=20 in http://mvvmcross.wordpress.com)
You could implement ViewModel binary properties which mirror your View and map to your three state enum
You could use a ValueCombiner within the Tibet binding system - it should be relatively straight-forward to work out a combiner based on top of something like MvxSingleValueCombiner.cs
Alternatively/additionally, please do also consider raising a Feature and/or Pull Request for this 'do nothing' type of functionality to be included in the TryGetValue/SetValue methods in https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Bindings/SourceSteps/MvxSourceStep.cs#L66 - but obviously the timeline on that might be longer.

Itcl Appropriate return value of configbody

I want to return from a configbody but cannot do so explicitly without causing the variable not to be set.
I'd like help understanding the behavior I'm seeing. Please consider the following code (using Itcl 3.4):
package require Itcl
catch {itcl::delete class Model}
itcl::class Model {
public variable filename "orig"
}
itcl::configbody Model::filename {
if 1 {
return ""
} else {
}
}
Model my_model
my_model configure -filename "newbie"
puts "I expect the result to be 'newbie:' [my_model cget -filename]"
When I return empty string, filename is not set to the new value. If I do not return but just allow the proc to fall through, filename does change. You can see this by changing the 1 to a 0 in the above code.
I suspect its related to the following statement:
When there is no return in a script, its value is the value of the last command evaluated in the script.
If someone would explain this behavior and how I should be returning, I'd appreciate the help.
Tcl handles return by throwing an exception (of type TCL_RETURN). Normally, the outer part of a procedure or method handler intercepts that exception and converts it into a normal result of the procedure/method, but you can intercept things with catch and see beneath the covers a bit.
However, configbody does not use that mechanism. It just runs the script in some context (not sure what!) and that context treats TCL_RETURN as an indication to fail the update.
Workaround:
itcl::configbody Model::filename {
catch {
if 1 {
return ""
} else {
}
} msg; set msg
# Yes, that's the single argument form of [set], which READS the variable...
}
Or call a real method in the configbody, passing in any information that's required.