What would be the best way to add some directive, e.g. ng-focus-if conditionally to the form's input element when using angular-formly with custom templates?
I would like to use it like this:
$scope.formFields = [
{
key: 'email',
type: 'input',
templateOptions: {
type: 'email',
placeholder: 'Your E-Mail address',
required: true,
focusIf: 'some-expression' // <--- optional directive configuration here
}
}
];
The idea is to apply the directive only when configuration option is actually provided.
You can combining angular-formly attributes with ng-focus-if attributes or any others custom attributes by using ngModelAttrs.
in your case your code should be like:
$scope.formFields = [ {
key: 'email',
type: 'input',
ngModelAttrs: {
focusIf: {
attribute: 'focus-if' //directive declaration
}
},
templateOptions: {
type: 'email',
placeholder: 'Your E-Mail address',
focusIf: '', //directive default value
required: true
}
}]
this is a working demo that can help you:
I've managed to figure out how to achieve the desired behavior, thanks to #kentcdodds and #aitnasser.
Just wanted to share the extended version here.
The idea is to use ngModelAttrs property when defining your type:
formlyConfigProvider.setType({
name: 'input',
template: '<input ng-model="model[options.key]">',
defaultOptions: {
ngModelAttrs: {
focusIf: {
attribute: 'focus-if'
}
}
}
});
Make sure not to provide the default value for the focusIf. This will prevent addition of the directive on the input element by default.
And then set the required expression on your field:
$scope.formFields = [
{
key: 'email',
type: 'input',
templateOptions: {
type: 'email',
required: true,
placeholder: 'E-Mail',
focusIf: 'true' // Or any other Angular expression
}
}
];
Feel free to play with this JSBin.
Related
I am creating a custom plugin where I need to list some stuff in the backend area. Each item in the list has the option to open a detail window where I want to display some info and a SELECT OPTION field but not sure how to create it. That field is just to select the option you want and save it in the database.
Is it possible to create it in myplugin/Resources/views/backend/my_plugin/model/product.js file?
I have something like this (sample):
Ext.define('Shopware.apps.MyPlugin.model.Product', {
extend: 'Shopware.data.Model',
configure: function() {
return {
controller: 'MyPlugin',
detail: 'Shopware.apps.MyPlugin.view.detail.Product'
};
},
fields: [
{ name : 'id', type: 'int', useNull: true },
{ name : 'Name', type: 'string' },
{ name : 'Lastname', type: 'string' },
{ name : 'Date', type: 'date' },
{ name : 'Color', type: 'SELECT?' }
]
});
Of course the Color field doesnt recognize the SELECT there but I was wondering if there's another word for it?
I was hoping to create that new field like this:
fields: [
...
{
name : 'Color',
type: 'SELECT?',
values: {'green', 'blue', 'red'}
}
]
If I am completly wrong could you please guide me where to create this field?
Thanks in advance.
You're defining a model, not a plugin and it looks like you want to configure 'Color' as an enum? Am I right?
The standard types are:
Ext.data.field.Field //(Default, implies no conversion)
Ext.data.field.String
Ext.data.field.Integer
Ext.data.field.Number
Ext.data.field.Boolean
Ext.data.field.Date
(see documentation under Field Types)
You can probably just use a string unless you want model validation...
You could create a custom type, extended from string or field and use a custom validator. (see same page under Validation)
Example:
Ext.define('App.field.Color', {
extend: 'Ext.data.field.Field',
alias: 'data.field.color',
// Match list of colors
validators: {
type: 'list',
list: ['green', 'blue', 'red']
}
});
Ext.define('App.model.Product', {
extend: 'Ext.data.Model',
fields: [
{ name : 'id', type: 'int', useNull: true },
{ name : 'Name', type: 'string' },
{ name : 'Lastname', type: 'string' },
{ name : 'Date', type: 'date' },
{ name : 'Color', type: 'color' }
]
});
Here's the screenshot of my ui-grid.
Here's the code that creates that filter.
{ field: 'channel_type', displayName: "Type", filter: {
type: uiGridConstants.filter.SELECT,
selectOptions: [
{ value: 'HD', label: 'HD' },
{ value: 'SD', label: 'SD' }
]
}},
{ field: 'price', displayName: "Price", enableFiltering: false, enableSorting: false},
My data is loaded in uigrid from rest api call.
I really can't figure it out from where is it adding that blank option. I haven't found any solution to this issue. Please help me in solving this problem.
Its a known issue, see ui-grid issues
The solution (workaround) is to add some custom style:
#grid1 div div select option:first-child[value=""] {
display: none;
}
Demo Plunker
You have to use filterHeaderTemplate and create your dropdown in it. Here is the example:
field: 'yourField',
filterHeaderTemplate: '<div class="ui-grid-filter-container" ng-repeat="colFilter in col.filters"><select class="grid-filter-control" ng-model="colFilter.term" ng-options="option.value as option.label for option in colFilter.selectOptions"></select></div>',
filter: {
disableCancelFilterButton: true,
term: '',
type: uiGridConstants.filter.SELECT,
selectOptions: [{ value: '', label: 'All' },
{ value: '1', label: 'Something' },
{ value: '2', label: 'Something Else' }]
}
Defining term will select your first option and the empty one is not going to show.
In my store I have a field called CreditName. In my view I am trying to check if CreditName is not null and if it is not enter it into my filefield. I have added a listener to my filefield that will enter text into the filefield. What I am having trouble with is getting CreditName into the filefield. I know that it is reading from my store because other fields are appearing properly.
Here is my code for my filefield
xtype: 'filefield',
buttonText: 'Select A File',
fieldLabel: 'File',
name: 'Credit',
labelWidth: 50,
msgTarget: 'under',
return true;
},
listeners: {
render: function (comp) {
comp.setRawValue(CreditName);
}
}
Here is the store code
fields: [ {
name: 'PartyId',
type: 'string'
}, {
name: 'CreditName',
type: 'string',
critical: true
}],
proxy: {
type: 'ajax',
url: 'api/parties',
reader: {
type: 'json'
}
}
PartyId shows up fine, here is the code for that, it is in the same view as filefield
{
xtype: 'displayfield',
name: 'PartyId',
fieldLabel: ' Party ID'
},
In your config of 'filefield', you have to use same name as 'name' property in store. In your case, it should be name: 'CreditName', not 'Credit'.
--edit--
You can get model values in 'render' listener like this:
render: function (comp) {
var model = comp.getModelData(),
value = model.get('CreditName');
comp.setRawValue(value);
}
I'm using Angular Formly and works very well if the model is a value of the scope, like a string:
{
key: 'name',
type: 'input'
}
The problem is that I'm using a more elaborated object to handle the model, with "controller as" syntax and the name as part of the user object:
vm.user = {name: 'john', lastname: 'doe'}
And then of course, the key would be:
{
key: 'user.name',
type: 'input'
}
(Usually the vm is taken out of the key in formly notation).
The problem is that Formly uses a bracketed notation to handle the model:
template = '<input ng-model=\"model[options.key]\">'
That when processed, spits out this output:
<input name="bd.form_input_user.name_1" type="text" ng-model="model.user.name">
Of course, the model doesn't have the user object and empty fields show.
So, my question is: How can I pass or link the appropriate object to the formly model when it's a more complex object?
Thanks in advance.
The model can be defined both at the form and the field level, so it is easy to use any property in an object graph as a form field. An example:
Markup:
<div ng-controller="MyCtrl as vm">
<formly-form model="vm.data" fields="vm.userFields">
<button type="submit" class="btn btn-default" ng-click="vm.submit(vm.user)">Submit</button>
</formly-form>
</div>
JavaScript:
angular
.module('myApp', ['formly', 'formlyBootstrap'])
.controller('MyCtrl', ['$scope', function($scope) {
var vm = this;
vm.data = {
user: {
name: 'john',
lastname: 'doe'
},
extra: 'extra'
};
vm.userFields = [
{
model: vm.data.user,
key: 'name',
type: 'input',
templateOptions: {
type: 'text',
label: 'Name',
placeholder: 'Enter name'
}
},
{
model: vm.data.user,
key: 'lastname',
type: 'input',
templateOptions: {
type: 'text',
label: 'Lastname',
placeholder: 'Enter lastname'
}
},
{
key: 'extra',
type: 'input',
templateOptions: {
type: 'text',
label: 'Extra',
placeholder: 'Enter extra'
}}
];
}]);
A fiddle: http://jsfiddle.net/masa671/c37gxg3h/
Help me please.
Models have built-in support for validations, which are executed against the validator functions in Ext.data.validations.
My code:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [{
name: 'name',
type: 'string'
},{
name: 'age',
type: 'int'
},{
name: 'phone',
type: 'string'
},{
name: 'gender',
type: 'string'
},{
name: 'username',
type: 'string'
}],
validations: [
{
type: 'length',
field: 'name',
min: 2
},{
type: 'format',
field: 'username',
matcher: /([a-z]+)[0-9]{2,3}/
}]
});
var person = Ext.create('User', {
name: 'Eugene',
username: 'Popov',
gender: 'F',
age: 300,
Married: false
});
console.log(person.get('name'))
person.set('name','U');
console.log(person.get('name'))//U
});
I've read that the model can filter data .
What is the principle of their work?
Why I can write wrong values in my example?
Thanks!
Model validations don't reject changes by themselves. Editing a model through some other component (like stores or grid editors) may provide this feature. Validations only come into play when calling the validate or isValid methods on a model.
If your models are part of a store, you can listen for the store's update event (link to docs). From within the event handler, you can validate the model and reject any changes you want.
// Simple demonstration
store.on('update', function (store, model, operation) {
if (operation === Ext.data.Model.EDIT && !model.isValid()) {
model.reject();
}
});