Angular ui-grid , add custom message to editableCellTemplate - angularjs

I need to add a custom error message to cell when it is in editable mode, basically i just need to add message to the editable html template as follow
<a href=\'#\' data-toggle=\'tooltip\' data-placement=\'top\' title=\'error!\' ng-show=\'!inputForm.$valid\'>errMsg - {{customMsg}}</a>
i have just bind the customMsg to the global scope just for testing purposes , but still it doesnt seems to be appearing. sample plunker added here, it would be a great help if you can tell me what i am doing wrong here
Thanks

You might want to take a look at this answer
https://stackoverflow.com/a/28127498/1585304
When you are working with the ui-grid, you are actually working in an isolated scope.
This means that you cannot access to the parent scope simply by type the name of the var into your html.
In order to access to your customMsg variable, you need to refer to the parent scope using grid.appScope.
Your column definition should look more like this.
{
field: 'company',
displayName: 'Company',
enableColumnMenu: false,
editableCellTemplate: "<div><form name=\"inputForm\">
<input type=\"INPUT_TYPE\" ng-class=\"'colt' + col.uid\"
ui-grid-editor ng-model=\"MODEL_COL_FIELD\" minlength=3
maxlength=10 required><a href=\'#\' data-toggle=\'tooltip\'
data-placement=\'top\' title=\'error!\'
ng-show=\'!inputForm.$valid\'>errMsg - {{grid.appScope.customMsg}}
</a></form></div>"
}
The only problem is that is really hard to see the message since the form is almost completely hidden by the row.
Hope this helps.

Related

How to add validation to Umbraco's custom backoffice section?

I've created a custom section in my Umbraco back-end, and I'm trying to create some forms to capture data however I've been unable to fully understand how the umbraco directives work when it comes to validation.
As an example, I'm trying to capture some basic data and save it using the following:
<form name="myForm">
<umb-property property="form.properties.name">
<umb-property-editor model="form.properties.name"></umb-property-editor>
</umb-property>
<umb-button type="button"
label="Save"
button-style="success"
action="save()">
</umb-button>
And in my controller:
$scope.form: {
properties: {
name: {
alias: 'name',
label: 'Display name',
description: '',
value: '',
view: 'textbox',
validation: {
mandatory: true
}
}
}
I would have thought the 'validation' property would be where I can set the validation necessary on the property, however that doesn't seem to be the case. All that seems to do is highlight the property with a red asterix to indicate it's required rather than do any validation.
I've taken a look at the backoffice documentation here however it's unfortunately lacking any code examples and I'm puzzled how this is supposed to work.
I've looked at the other sections, particularly the create user form to see if I can pick anything up there but the only thing I've noticed is the 'valFormManager' directive which may be involved somehow.
I've also tried the obvious things like putting ng-required on the editor and property but neither has done the trick.
Is there any documentation for any of this? It's quite frustrating trying to work out how it's all supposed to work!
Thanks

Angular UI Bootstrap Datepicker is-open

I've been working on this for a while now, and am not sure where to go from here.
I am using Jade for my templates inside my app, and am trying to use the UI Bootstrap date picker as well. In UI Bootstrap 0.10.x everything was working fine, but in 0.13.3 I can't get the is-open attribute on the datepicker to work properly. Here is the jade template excerpt:
input(type="text", ng-model="item.exp_date", datepicker-popup="{{datepicker.format}}", min-date="{{datepicker.minDate}}", is-open="{{datepicker.opened}}", close-text="{{datepicker.closeText}}").form-control
span.input-group-btn
button(type="button", ng-click="openDatepicker($event)").btn.btn-default
i.glyphicon.glyphicon-calendar
You can see that for several attributes I'm using angular expressions to get preset values (i.e. datepicker-popup="{{datepicker.format}}". However, that expression does not work when I try to do the same thing with is-open. All the others work fine, and if I just put is-open="true" in for the attribute, the datepicker at least shows up on page load. The problem is you can never open it again.
Here's the pertinent controller code:
$scope.datepicker = {
format: 'MM-dd-yyyy',
minDate: new Date(),
closeText: "Close",
showWeeks: false,
yearRange: 50,
opened: false
}
$scope.openDatepicker = function($event) {
$scope.datepicker.opened = true;
}
and the error in the browser that pops up:
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 2 of the expression [{{datepicker.opened}}] starting at [{datepicker.opened}}].
http://errors.angularjs.org/1.4.5/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7Bdatepicker.opened%7D%7D&p4=%7Bdatepicker.opened%7D%7D
at REGEX_STRING_REGEXP (http://localhost:3030/vendor/angular/angular.js:68:12)
at Object.AST.throwError (http://localhost:3030/vendor/angular/angular.js:12967:11)
at Object.AST.object (http://localhost:3030/vendor/angular/angular.js:12954:16)
at Object.AST.primary (http://localhost:3030/vendor/angular/angular.js:12862:22)
at Object.AST.unary (http://localhost:3030/vendor/angular/angular.js:12850:19)
at Object.AST.multiplicative (http://localhost:3030/vendor/angular/angular.js:12837:21)
at Object.AST.additive (http://localhost:3030/vendor/angular/angular.js:12828:21)
at Object.AST.relational (http://localhost:3030/vendor/angular/angular.js:12819:21)
at Object.AST.equality (http://localhost:3030/vendor/angular/angular.js:12810:21)
at Object.AST.logicalAND (http://localhost:3030/vendor/angular/angular.js:12802:21) <div ui-view="locations" class="ng-scope">
Like I said, the is-open attribute is the only one having this issue. If you have any suggestions for fixing the issue or a work around I'd love to hear it. Thanks!
Of course right after I posted the question, I figured out the problem. Apparently for that attribute, the {{ }} is unnecessary. All the other attributes need the curly braces, but that one doesn't. It must be because it assumes you will be adding in a variable to toggle the visibility.
Whatever the reason, I figured it out and got it working again. I'll leave this up in case anyone else gets as stuck as I did and can't get it working again.
For the atribute of angularjs (whatever) the {{ }} is not necesary, in this atribute you are in angularjs, and not needed call to angularjs.

ng-click used inside ng-grid

I'm hoping you can help me figure out how to merge my ng-click event into my code. I've been trying to figure it out all weekend. I found this ng-click event jsfiddle: http://jsfiddle.net/nisham/09k8f5s4/97/ that I want to use inside my project.
I want users to be able to see the grid and simply click a box and have it switch between 'Y' and 'N', back and forth.
I have tried many ways of incorporating the ng-click event into my webpage. Here is a plunker I made to make it easy to share: http://plnkr.co/edit/eTf96oJLIjtM7UiB742e?p=preview
I guess I need to figure out how to define the scope differently to add my function?
Do I need to use a to call the ng-click?
Do I need to add variables into my $scope.myData? Something like:
$scope.myData = [
{ time: "8:00am", monday: val, tuesday: val,
??????????????
You can do it by using cellTemplate for a column in column defination:
{
field: 'monday',
displayName: 'Monday' ,
cellTemplate: '<div class="ngCellText"><div ng-click="onClickFn(row.entity, col.field)">{{row.getProperty(col.field)}}</div></div>',
enableCellEdit: false
}
Check this working plunker.

Bootstrap Datepicker with angular JS issue (again)

I am trying to create an editable Grid in which there is a dateField which is editable. The cell will be shown as editable only if Cell is focussed
$scope.gridOptions = {
data: 'result',
enableCellSelection: true,
enableRowSelection: false,
enableCellEditOnFocus: true,
multiSelect: false,
columnDefs: [
{ field: 'name', displayName: 'Name', enableCellEdit: false, width: 60 },
{ field: 'age', displayName: 'Age', enableCellEdit: false, width: 60 },
{ field: 'sex', displayName: 'Sex', enableCellEdit: false, width: 90 },
{ field: 'dob', displayName: 'DOB', width: 150,
editableCellTemplate: '<input type="text" datepicker-popup="dd/MM/yyyy" is-open="true" ng-input="COL_FIELD" ng-model="COL_FIELD" datepicker-append-to-body=true />',
}
]
};
In the editableCellTemplate, if i am not using is-open="true", then pop up is not coming. If i am not using ng-input="COL_FIELD", focus is not getting removed from any cell. So, datepicker is not getting hidden .But if i am using both then, value is not getting selected. In the console the error says Expression 'true' used with directive 'datepickerPopup' is non-assignable!
There are a lot of questions on stackoverflow for this. I tried almost all, but no sucess.
What can be done? How can i remove the error? Please provide me with a working plunker. I am not able to create this issue with the plunker.
Edit
I think, i could not remove the error. The error is still the same
Expression 'true' used with directive 'datepickerPopup' is non-assignable!
How can i remove it? After removing it, i am sure it will work. I tried taking it as a scope variable, and referencing it, but value is not getting replaces as true in when i am checking it using Inspect element. If i am using it as a variable and concatenating the value in template like 'is-open="' + $scope.dateFormat.opened + '"' , still the same error is there.
Edit 2
What is this is-open used for? Somewhere i see its value equlas to true, somewhere just opened. In one of the example over here in Stackoverflow its just opened1 and opened2. What is this? And how to use this?
I have removed the error using bcombs technique
Edit 3
After further debugging, i found that, datePicker is getting opened (if i am using the method mentioned by bcombs)but, it is getting closed as soon as it is opening.
$scope.$on('ngGridEventStartCellEdit', function () {
debugger;
});
Edit 4
From more manipulation what i concluded is
If ng-input is used, then it breaks the 2 way binding. i.e If u change the date value textfield, then in the datePicker it will be reflected, but if you will try to change the value using datePicker, it will not be reflected in textField.
If you remove ng-input, this 2 way binding, remain correct, so it works, but this causes ngGridEventEndCellEdit event NOT fired. so, the focus is not getting lost. Value is getting selected, datePicker is getting closed (if instead enableCellEditOnFocus:true, i use enableCellEdit:true), but focus remains on the textField..
Need help. Hope the update helps in solving the issue
I'm no expert on bootstrap directives or their angular implementations... But to directly answer the question of how to remove the bug:
I'm fairly certain that the is-open attribute cannot be a primitive value. It needs to be a variable that will hold the (boolean) state of whether this particular widget is open. In my code, I use a single object to hold these flags for all my datepickers, such as:
openDatePickers: {}
Then, in the cellTemplate string, I give it a unique id such as:
' is-open="openDatePickers[\'dob_{{row.entity.name}}\']" '
(note that I'm using the "name" property to match your example, but a unique ID is preferred).
Edit in response to comment:
The celltemplate has access to its controller scope, so the simplest approach is to simply declare:
$scope.openDatePickers={};
As for how this works, it depends a little on which codebase you are using.
I'm using angular-ui, and in ui-bootstrap-tpls-0.8.0.js at line 1140 you can see where the directive manages the "is-open" attribute.
If the attribute is not supplied, the directive manages this flag internally with a closure, but behavior is different When the attribute IS supplied. The way the assignment works is straightforward in both cases: the variable (whether the internal closure, or the one you supplied in the attribute) is simply toggled between states.
Edit in response to your debugging
As far as the focus thing: I don't use ng-input or enableCellEditOnFocus. I do use:
enableCellSelection: true
...and our client didn't want manual edits of the field to be allowed, so my input element has:
ng-readonly="true"
This should be a functional workaround for your issue as long as your use case doesn't require that you allow manual edits to the input field.

Setup bi-directional binding from an object defined in an html attribute in AngularJS

I have implemented a remote validation directive which queries a specified JSON API endpoint once an input is blurred. It expects the response { valid: true|false }.
I now have to extend it to allow for it to send a request involving multiple values from the parent scope.
My tag definition looks as follows:
<input remote-validate endpoint="/api/action/:value" ng-model="MyInput" />
where :value is substituted with a urlencoded value of $scope.MyInput.
This is working well.
What I require is given an endpoint like this /api/action/:value/:person/:thing, the :person and :thing substitutions are bound to the parent scope values.
My initial thought is to have a bindings attribute which maps the parent scope to the endpoint.
<input remote-validate endpoint="/api/action/:value/:person/:thing" bindings="{person: 'firstName', thing: 'thingName'}" ng-model="MyInput" />
(...)
<input ng-model="firstName" /> <input ng-model="thingName" />
given var bindings = scope.$eval(attrs.bindings); is there any way to loop through the bindings object and create a two way binding to the parent scope?
EDIT: A workaround may be to do this:
<input validate-remotely
endpoint="api/action/:value/:param1/:param2"
param1="person"
param2="thing" />
which obviously means I can only use the number of parameters I specify in the scope definition. Which is a good work around for me here. Would be nice to know if there was a way to create these bindings dynamically at compile/link time.
I can provide a fiddle but I don't have the time right now, so I'm hoping that someone will have a good idea if/how this is possible.
As I learned yesterday, you can use $parse on your 'binding' attributes. See this post. This is a good way to $watch an attribute for changes that come from parent or children
Example:
<div parse-test bindings="{person: 'firstName', thing: 'thingName'}"></div>
// in your directive link function:
scope.bindings = $parse(attrs.bindings)(scope);
scope.$watch('bindings', function(val){
for (i in scope.bindings){
scope[i] = scope.bindings[i];
}
}, true);
Experiment with this plunk
This is how I solved it in a not so ideal way.
See this plunker, which has a copy of the directive I use live and works well in my app but doesn't work in Plunker (I expect the randomly chosen plunker api endpoint to be called and fail, but it is not called due to some strange errors I don't care to debug).
The problem I had with the proposed workaround in the EDIT of this question is that it seems you cannot use scope and require in the same directive. I would love it if someone could elaborate on if this is the case and why.
The Workaround
I used a params attribute to specify additional data in object notation to be extended to go to the resource request. I used the handlebars syntax in the params attribute to dynamically change the object notation string.
<input ng-model="value2" ... />
<input validate-remotely
endpoint="/api/:value/?thing=:anotherValue"
params="{ anotherValue: '{{ value2 }}' }" ... />
Not so great :/ but it works.
Then on blur of the validated input, I re-$eval the object string (app.js:40 in the plunker) and extend the resources data to include this object, which using ngResources colon (:) notation, replaces the URL.
The validation has 3 states:
remoteValidityPending: field validation fails because it is still being checked - good for showing a spinner.
remoteValidityUnchecked: The field has changed since it has been checked but has not yet blurred - ensures that any `ng-disable="form.$invalid"' submit buttons stay disabled until we know that the backend has returned a response.
remoteValidity: If this passes, the fields endpoint has been called and '{valid: true}' has been returned from the server.
I'm almost certain there are better/different ways to solve this, and I'll be happy to change the answer if someone improves this directive. I hope this helps someone out there.

Resources