extjs6 bind label visibility - data-binding

I am looking to bind the visibility of a button to a parameter with some difficulty. In xamarin I would add binding in xaml to a parameter, then in viewmodel I would have a getter/setter and simply put my simple true/false formula in the getter.
What would be the equivalent in extjs. Right now in my view I have,
{
xtype: 'button',
text: 'Upload LiveEnd',
//itemId: 'buttonUploadLiveEnd',
handler: 'onUploadLiveEnding',
margin: '5px 5px 0 0',
bind: {
hidden: '{param}'
}
}
In my viewmodel I have a parameter
data: {
param: true
}
That works to hide button, But when I try to change the variable in my controller it doesn't change the view even though I think the parameter is being changed. Is there something simpler like getter/setter from xamarin?

To change the value of data fields of view model you can use the set method on viewmodel. So to achieve your target yo can use below syntax.
vm.set('param', false);
Here vm is the reference of your viewmodel.

Related

How to correctly bind a form element to newly created oData Entity in SAPUI5?

I have implemented an oData Service into my SAPUI5 application.
On pressing a button the oData Model createEntry() is triggered which returns a Context with the newly created entity.
As per the SAPUI5 documentation - Documentation (Creating Entities) it should be enough to call setBindingContext(oContext) on my form to bind my new entity to my form.
But no matter how I try, I can't seem to get the binding working. The input fields remain empty (although the entity has set properties).
Do I need to keep a special syntax in mind when trying to do this kind of binding with an oData Model?
My form:
<f:SimpleForm id="form" editable="true" layout="ResponsiveGridLayout" title="Address" labelSpanXL="3" labelSpanL="3" labelSpanM="3"
labelSpanS="12" adjustLabelSpan="false" emptySpanXL="4" emptySpanL="4" emptySpanM="4" emptySpanS="0" columnsXL="1" columnsL="1" columnsM="1"
singleContainerFullSize="false">
<f:content>
<Label text="Recno"/>
<sf:SmartField id="recno" value="{recno}"/>
</f:content>
</f:SimpleForm>
My method that opens my dialog containing the form:
openCreateDialog: function() {
this.getOwnerComponent().getModel("oDataModel").refreshSecurityToken(function() {
var oContext = this.getOwnerComponent().getModel("oDataModel").createEntry("/head", {
properties: {
recno: "100"
}
});
this.byId("form").setBindingContext(oContext);
}.bind(this), function(data) {
console.log(data);
}, true);
this.byId("CreateHeadDialog").open();
},
EDIT
I already tried {oDataModel>xxx} but this doesnt work.
On the other hand, after I made my oDataModel a nameless model it seems to work fine. The smartfield correctly shows the right value, but changes I make in the UI are not applied to the property my smartfield is bound to.
When I submit pending changes of my oDataModel, all properties of my entity remain undefined, although I filled the smartfields with correct values.
You are using a named model: your model name is "oDataModel" evidenced by this in your code:
.getModel("oDataModel")
When using binding syntax in your XML View you need to prefix the field with the named model name as below:
<sf:SmartField id="recno" value="{oDataModel>(your-path-to-object)recno}"/>
If it's not in a list then you would need to reference the field as below (or navigate according to the position of recno in your json hierarchy:
<sf:SmartField id="recno" value="{oDataModel>/recno}"/>

Ampersand's booleanClass to toggle, add/remove a property

I found this documentation but I still couldn't figure out how I will use it in a code. https://ampersandjs.com/docs/#ampersand-dom-bindings-booleanclass
What I want to do is use Ampersand's binding rather than using Jquery $() to capture or fire an event when I click an element. Can someone please show an example of an ampersand code that will toggle, add/remove class that I can use with css. This will be helpful in for example expanding or collapsing an html element.
It seems like you are confusing two things here: events and bindings. Bindings are binding specific variables (defined in props or session), while events are triggering events, like jquery does. Here is an example of using these two together:
module.exports = AmpersandView.extend({
template: yourTemplate,
props: {
switchedOn: ['boolean', true, false]
},
bindings: {
'switchedOn': {
type: 'booleanClass',
name: 'active',
selector: '#your-selector'
}
},
events: {
'click #your-selector': function(e){
this.switchedOn = !this.switchedOn;
var el = e.target;//this is the element which triggered the event. In jquery it would be 'this' inside of the handler
}
}
})
Here I define the variable switchedOn to which the state of class active of #your-selector is bound.
Personally, I think it's a bit too much if you need just to toggle an element. In many cases jquery will require less code.

Angular2 two-way data binding

I know Angular2 doesn't have two-way data binding but is there a way to mimick the two-way data binding behavior from Angular1.x?
Note - scroll down the answer for ng-model binding
You could actually do that, just that you need to invoke internal changelistener tick (similar to digest) to update binding in the zone, You can just add a (keyup) event for that. Similarly you could use directive bindings as well with properties dictionary of component settings.
Example:-
<input #label (keyup)>
<!-- variable #label represented as the element itself and accessible as property on controller instance
You can even bind keyup to a function or another another function and pass value from the label property-->
Display as:
<p>{{label.value}}</P>
Parent Component has a textbox and a label.
import { Component, bootstrap} from '#angular/core';
import {Display} from 'display';
#Component({
selector: 'my-app',
template: `<p><b>Parent Component:</b><p><input #label (keyup) (change)="handleChange(label.value)">
<p>{{label.value}}</P> <display [text]="label"></display></p></p>`,
directives: [Display]
})
class MainComponent {
label: any;
constructor() {
}
handleChange(label){
this.label = label;
console.log(this.label);
}
}
Now displaying it in child component as well:
#Component({
selector: 'edit',
template: `<p><b>Child Component:</b></p>{{text.value}}`
})
export class Edit {
#Input() text:any;
}
Demo
Update - ng-model for 2-way binding
Though Angular2 is one-time bound by default, ngModel sugar has been introduced to achieve 2-way binding. With that you could do for instance:
<input ngControl="name" [(ngModel)]="name">
Here usage of square brackets ([..]) suggests the property binding and round brackets ((..)) for event binding. Basically when you use ng-model, you are enabling both the bindings ngModel is more of an event. Behind the scenes it creates an observable event(with EventEmitter) to track the value changes in the bound element and update the bound property respectively.
For example:-
Include formDirectives:
import {FORM_DIRECTIVES} from '#angular/common';
and with form
<form (ngSubmit)="onSubmit()" let-f="form">
<input ngControl="name" [(ngModel)]="name">
<button>Click me and check console</button>
</form>
without form
<input [(ngModel)]="name">
<button (click)="onSubmit()">Click me and check console</button>
not necessary anymore
include formDirectives dependency in view annotation.
#Component({
template: .....,
directives: [FORM_DIRECTIVES]
})
Demo
Also read the nice write up from Victor Savkin on Two-way binding in angular2 by creating the ng-model event and how it works.
You can now simply do this by using ngModel using the following syntax:
<input [(ngModel)]="myProp" />
The combination of the square and round brackets means "two-way binding".
Please see the plunk here
Yes there is two-way binding in angular2. See here: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
So, how to use it in custom components?
What I like to do is something this:
private currentSelectedItem: MachineItem;
#Output() selectedItemChange: EventEmitter<MachineItem> = new EventEmitter<MachineItem>();
#Input() set selectedItem(machineItem: MachineItem) {
this.currentSelectedItem = machineItem;
this.selectedItemChange.emit(machineItem);
}
get selectedItem(): MachineItem {
return this.currentSelectedItem;
}
And use it like
<admin-item-list [(selectedItem)]="selectedItem"></admin-item-list>
You can also emit the new value where it is actually changed. But I find it quite convenient to do that gloabaly in a setter method and don't have to bother e.g. when I bind it directly to my view.
You can do this by attaching to the events on the input field and updating the internal value as is done in this example:
http://plnkr.co/edit/lOFzuWtUMq1hCnrm9tGA?p=preview
Create a component that has an internal attribute that holds the label this.label and a callback changeLabel that expects an event object
#Component({
selector: 'app',
templateUrl: 'bound.html'
})
class App {
label: string;
constructor() {
this.label = 'default label'
}
changeLabel(event) {
this.label = event.target.value;
}
}
bootstrap(App);
The create your template and attach the callback to the appropriate event (you could attach it to the keypress event but then you might need a timeout. I attached it to the change event for simplicity (which means you might need to tab off the input to see the update).
<label for="myinput">{{label}}</label>
<input id="myinput" type="text"/>
<p></p>You can change the label above by typing something below</p>
<label for="labeltext">New Label Text</label>
<input type="text" id="labeltext" (change)="changeLabel($event)"/>
There is another way to trick Angular2 into two-way binding. Don't pass a property but an object into the component. If you pass an object via one-way binding all of its properties are in fact two-way bound.
It makes the component less versatile as it needs to know the object but in many cases it's still useful.
I have a component that looks like this:
import { Component, Input } from "#angular/core";
import { NgSwitch, NgSwitchWhen, NgSwitchDefault } from "#angular/common";
export class Movie
{
public Title: string;
public Rating: number;
public Seen: boolean;
}
#Component
({
selector: "hh-image-checkbox",
template: `
<div [ngSwitch]="movie.Seen">
<div *ngSwitchWhen="true">
<img src="/Content/res/CheckTrue.png" (click)="onClick()">
</div>
<div *ngSwitchDefault>
<img src="/Content/res/CheckFalse.png" (click)="onClick()">
</div>
</div>
`,
directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault]
})
export class ImageCheckboxComponent
{
#Input() movie: Movie;
public onClick()
{
this.movie.Seen = !this.movie.Seen;
}
}
It is invoked like this:
<hh-image-checkbox [movie]="movie"></hh-image-checkbox>
The movie object itself is one-way bound but all of its properties can be used for two-way binding.
Here is a simple plunker which demonstrates one way, two way and event driven approaches in action according to Angular2 2.0.0-beta.17
http://plnkr.co/eXZMoU
Two-way Event and property
<input [(ngModel)]="name" />
One way property
<input [value]="name" />
Event driven
<input (input)="name=$event.target.value">
We can dig Angular docs for more
[UPDATE 1/26/2020]
Since Angular2 beta libs are removed from project CDN ! above plnkr link doesn't work anymore.
Use below new plnkr Angular 6+ page , I ported previous page to NPMJS, new angular edition and new plnkr!
http://next.plnkr.co/edit/4okdOSgw3SMvdktR?preview
From the Docs:
Two-way binding ( [(...)] )
You often want to both display a data property and update that property when the user makes changes.
On the element side that takes a combination of setting a specific element property and listening for an element change event.
Angular offers a special two-way data binding syntax for this purpose, [(x)]. The [(x)] syntax combines the brackets of property binding, [x], with the parentheses of event binding, (x).
[( )] = BANANA IN A BOX
Visualize a banana in a box to remember that the parentheses go inside the brackets.
For more information, see
Angular Developer Guide - Template Syntax - Two-way binding
Angular #angular/forms API Reference - ngModel Directive
Its simple, try this;
<input [(ngModel)]="property" placeholder="property Value"/>
<h1>{{property}}</h1>

Model Binding With Disabled Textbox

I have a textbox that I am defining as
<%= Html.TextBox("Username", Model.Form.Username,
new { #class = "textbox", #disabled = "disabled" })%>
The action is defined as
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult EditLogin(LoginForm post) {
...
return View(model);
}
When I POST to this, Username will be blank. All other properties bind correctly, but if I change #disabled="disabled" to #readonly="readonly" the username binds properly and everything works.
It looks like model binding ignores values in disabled fields. Is there a way around this? I still need the field's value to bind to the model. I can use readonly but would prefer to use disabled so it is visually apparent to the user that they cannot edit the value of the field.
I believe a form field that is disabled does not submit anything. If you have a form and disable the foo field in that form, when you post the post will not have the value for the foo field. This is simply the nature of disabling a field in HTML and is not a MVC issue.
use readonly - will disable input but you'll still have it in the binding.
You could apply a style on the div to make it looked greyed out maybe?
<div class="editor-label">
#Html.LabelFor(model => model.FileName)
</div>
<div class="editor-field-greyed-out">
#Html.TextBoxFor(model => model.FileName, new { #readonly = true })
#Html.ValidationMessageFor(model => model.FileName)
</div>
If you want the value to be sent back, but not be editable, consider placing it in a hidden field. Obviously, don't do this for anything that requires a degree of security, since a user can tamper with it.
You can do a workaround by adding a hidden field with the same value ;)
<%= Html.Hidden("Username", Model.Form.Username)%>
As suggested in the comments, readonly instead of disabled can be an option but it will not work for select boxes. Instead of creating a hidden input, you can keep the inputs or selects as disabled and still pass the data by changing the disabled property with JavaScript at the submit.
Using jQuery it'd look like this:
$('form').on('submit', function(){
$('input, select').prop('disabled',false);
return true;
});
Easiest way to submit disabled fields is to copy them over to an invisible, non disabled control before submit. Some people create those controls manually and hook up to the on change event in jQuery to copy them on demand, but this solution below is generic, easy and less chatty - although one rule: you must create (render) a clean page after postback (so
$('#submitBtn').closest('form').one('submit', function() {
var $form = $(this);
// input, textarea, select, option, ----- button, datalist, keygen, output, optgroup
$form.find('input:disabled, textarea:disabled, select:disabled, option:disabled').each(function () {
var $item = $(this);
var hiddenItem = $item.clone();
hiddenItem.removeAttr('id');
hiddenItem.removeAttr('disabled');
hiddenItem.attr('style', 'display: none');
$item.after(hiddenItem);
});
});
#readonly = true does not work on my page. I did additional research. Here is the article that explains it
ReadOnly attribute doesn't work in ASP.NET MVC Models

Add support for fields to databound controls

For example when using a gridview. When you specify the columns
BoundField for example won't work if you are binding it to a field instead of a property.
I guess this is so because when the gridview is looking for the DataField property it looks for a property and not a field. Now the question is how can i change this behavior to make it possible to use fields. I know i have to inherit from the gridview, but i don't know where to go from there.
This functionality is so wrapped into the framework and wasn't designed for extensibility so no you can't change this behavior; the only thing you can do is to create wrapper objects or wrap fields with properties.
Or render the UI in your own way, which then you lose the GridView in-built functionality.
Wrap the fields with Properties
private string fieldA;
public string FieldA
{
get { return fieldA; }
set { fieldA = value; }
}

Resources