Make only one column editable - telerik-grid

My goal is to make a grid where only the checkbox (IsActive) is editable and it should be editable without having to press an edit button.
I would like for the checkbox to be bound to the model, instead of making a manual checkbox and then handle changes myself.
The result should look somewhat like this: http://demos.telerik.com/aspnet-mvc/razor/grid/headerfootertemplates
Model
public class MyModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
View
Html.Telerik().Grid(Model)
.Name("grid")
.Columns(column =>
{
column.Bound(x => x.Id);
column.Bound(x => x.Name);
column.Bound(x => x.IsActive)
.HeaderTemplate(#<text>#Html.CheckBox("checkAll")</text>);
})
.EnableCustomBinding(true)
.DataBinding(dataBinding => dataBinding.Server().Select("Index", "Stuff"))
.Render();
Is it possible?

Using Template seems like the only option.
I switched to Ajax binding so I'm using ClientTemplate
column.Bound(x => x.IsActive)
.ClientTemplate("<input type=\"checkbox\" name=\"checkedRecords\" value=\"<#= Id #>\" <#= IsActive ? \"checked='checked'\" : '' #> />")
.HeaderTemplate(#<text>#Html.CheckBox("checkAll")</text>);
Now I just need to figure out how bind a checkbox click to a command.Update().

Related

Adding Custom Entity Type in CRM Activity for selecting in Relative Entity

I have implemented CRM activity on the Custom page where the Key Field is SOOrder Type, SOOrder Nbr & Job Code which are stored in custom DAC. I have tried to add the Entity Type listed on Related Entity and I am not able to figure out how to do it. Pls let me know where to add or override the method to Implement the functionality
The following cod used to implement the CRM Activity
public sealed class SOOrderJobActivities : CRActivityList<PSSOOrderJob>
{
public SOOrderJobActivities(PXGraph graph)
: base(graph) { }
protected override RecipientList GetRecipientsFromContext(NotificationUtility utility, string type, object row, NotificationSource source)
{
var recipients = new RecipientList();
var order = _Graph.Caches[typeof(PSSOOrderJob)].Current as PSSOOrderJob;
if (order == null || source == null)
return null;
SOOrder ord = SOOrder.PK.Find(_Graph, order.OrderType, order.OrderNbr);
var contact = SOOrder.FK.Contact.FindParent(_Graph, ord);
if (contact == null || contact.EMail == null)
return null;
recipients.Add(new NotificationRecipient()
{
Active = true,
AddTo = RecipientAddToAttribute.To,
Email = contact.EMail
});
source.RecipientsBehavior = RecipientsBehaviorAttribute.Override;
return recipients;
}
}
Update
After going through the Acumatica code, I have done the following changes
#region Noteid
[PXNote(ShowInReferenceSelector =true,Selector =typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder,On<PSSOOrderJob.orderType,Equal<SOOrder.orderType>,And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType,Equal<Current<PSSOOrderJob.orderType>>,And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>>>>))]
public virtual Guid? Noteid { get; set; }
public abstract class noteid : PX.Data.BQL.BqlGuid.Field<noteid> { }
#endregion
The entity comes into selection, But I am not able to select the relative entity document and the value is not getting updated in the related entity field.
The above screenshot the select is missing and not able to select the document
The following steps I have done to add relative Entity for any Activity using custom DAC
1. Added ShowInReferenceSelector = true in PXNoteID field.
2. Added Selector in PXNoteID field
3. Decorated [PX.Data.EP.PXFieldDescription] attribute for Key fields
#region NoteID
[PXNote(ShowInReferenceSelector = true, Selector = typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder, On<PSSOOrderJob.orderType, Equal<SOOrder.orderType>, And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType,Equal<Current<PSSOOrderJob.jobType>>>>>>), DescriptionField = typeof(PSSOOrderJob.jobCode))]
//[PXNote(ShowInReferenceSelector = true)]
public virtual Guid? NoteID { get; set; }
public abstract class noteID : PX.Data.BQL.BqlGuid.Field<noteID> { }
#endregion
#region JobCode
[PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
[PXUIField(DisplayName = "Job Code")]
[PXDefault()]
[PXSelector(typeof(Search<PSSOOrderJob.jobCode, Where<PSSOOrderJob.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<PSSOOrderJob.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType, Equal<Current<PSSOOrderJob.jobType>>>>>>), typeof(PSSOOrderJob.jobCode), ValidateValue = false)]
[PSSOOrderJobNbr.Numbering()]
[PX.Data.EP.PXFieldDescription]
public virtual string JobCode { get; set; }
public abstract class jobCode : PX.Data.BQL.BqlString.Field<jobCode> { }
#endregion
This automatically fills the related entity field with Jobcode.
There still one issue I am facing is not able to access the selector due to Entity field width is more than the popup window and I do not know how to fix it.
This answer is to address the popup size only.
First, give browser zoom a try 'control' + 'minus' key. It might work as a quick workaround.
Otherwise, use the browser debugger feature. Open it with F12 key. Then use the browser debugger inspect element feature (1). Click on the smart panel (2). Go up a bit in html control hierarchy until you reach and select the smart panel root which is a table element (3). Change the width of the smart panel popup using the debugger CSS properties editor (4).
If selector control size increases automatically with window size; change the selector control width instead of popup width using browser debugger CSS property editor.

How to activate the filtering action for a user field added to a grid

I have a customization to the Release Time Activities screen (EP507020) where I add a user field. This user field will contain the result of fetching the Appointment status from the Appointments screen (FS300200) based on the Appointment ID that I've also added to the Release Time Activities screen grid.
This was done so that the process grid could be filtered for appointment status that were a certain value. The Appointment Status User field I've added contains the same attributes that the Status field contains on the Appointments screen, with the Cache extension looking as follows:
#region UsrApptStatus
public abstract class usrApptStatus : IBqlField
{
}
[PXDBString(1)]
[FSAppointment.status.ListAtrribute]
[PXUIField(DisplayName = "Appt Status",Enabled = false)]
public virtual string UsrApptStatus { get; set; }
#endregion
This works fine when I fetch the status as follows in a Graph extension:
protected virtual void EPActivityApprove_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var epactivityapprove = (EPActivityApprove)e.Row;
if (epactivityapprove != null)
{
FSxPMTimeActivity rowExt = epactivityapprove.GetExtension<FSxPMTimeActivity>();
if (rowExt != null)
{
var appointmentID = rowExt.AppointmentID;
var fsappt = (FSAppointment)PXSelect<FSAppointment,
Where<FSAppointment.appointmentID, Equal<Required<FSAppointment.appointmentID>>>>.Select(Base, appointmentID);
var epactivityapproveext = PXCache<EPActivityApprove>.GetExtension<EPActivityApproveExt>(epactivityapprove);
epactivityapproveext.UsrApptStatus = fsappt.Status;
}
}
}
The problem is that when I go to filter the Status column, no matter what I choose from the list of options, it clears all rows. I have no idea why this wouldn't work, but I'm sure I'm missing something.
Grid before filtering:
Filter:
Grid after filter:
It seems to me that changing the value in the RowUpdated event is interfering with the filter. If you wrote both extensions, it would help to have both custom fields in the same extension and use the PXFormula attribute to set the value of your status based on the AppointmentID field. This way you wouldn't have to rely on the event:
#region UsrApptStatus
public abstract class usrApptStatus : IBqlField
{
}
[PXDBString(1)]
[FSAppointment.status.ListAtrribute]
[PXFormula(typeof(Selector<appointmentID, FSAppointment.status>))]
[PXUIField(DisplayName = "Appt Status",Enabled = false)]
public virtual string UsrApptStatus { get; set; }
#endregion

Can't seem to expand an Image Navigation property with Breeze JS

I am using MVC, Entity Framework, Durandal and Breeze JS. I've got a user which looks like such (simplified):
public class User : EntityBase<Guid>, IAggregateRoot
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[ForeignKey("UserImage")]
public virtual Guid? ImageId { get; set; }
public virtual UserImage UserImage { get; set; }
}
The UserImage class looks like such. I know I should limit the size of the Image. (Maybe this is the issue?):
public class UserImage
{
public Guid Id { get; set; }
[MaxLength]
public byte[] Image { get; set; }
}
I've got an api function on the server to get the current user:
public IQueryable<User> GetCurrentUser()
{
IPrincipal principal = HttpContext.Current.User;
var users = _uow.Users.FindBy(u => u.UserName.Equals(principal.Identity.Name));
if (!users.Any())
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized));
}
return users;
}
And two calls on the client which get the current user. The first is in the shell:
function loadCurrentUser() {
return uow.CurrentUser.all().then(function (newUser) {
log('Welcome to the Site ' + newUser[0].FullName() + '!', newUser[0], true);
config.CurrentUser(newUser[0]);
return true;
});
}
The second is in a ManageUser viewmodel:
function activate() {
return uow.CurrentUser.all(['UserImage']).then(function (user) {
self.CurrentUser(user[0]);
return $.when(init()).then(boot());
}).fail(function() {
return router.activate('accounts/login');
});
}
Now I can load an Image into the ManageUser page and save and in fiddler it shows that the ImageId and Image are being sent across to the server. Then I checked the BeforeSaveEntity intercept and shows two entities being saved.
Updated User with ImageId set
New UserImage
The data is also visible in the database. Now when I refresh the Manage User page I can see the two GetCurrentUser calls in fiddler.
From the shell call I can see that the User is being returned and an ImageId is set but no UserImage was sent over because didn't expand the query.
From the Manage User call I see the User is returned but only the ImageId is sent over and the Image object was OMITTED from the JSON.
Has anyone come across this issue with images? All my other expands appear to be working correctly. Does anyone have any examples on using breeze to save just the filepath to the image and possibly using windows azure for media storage?
I know this probably won't answer your question but I would propose not sending the byte array to the client and rather have an Image Handler on the server side that takes an ImageId as a parameter and then return the image with the relevant Content Type set. An example of this can be found here.
By using this approach you could reference your image from HTML using an img tag with the source set to the Image Hander with the relevant ImageId.
An example using knockout for data binding would be:
<a data-bind="attr: {href: '/Image/' + User.ImageId()}"></a>
This approach enables you to easily add caching on both the server and client which will improve performance. It also removed the need to convert the byte array to an image on the client side, which may or may not be a pain.
Edit:
When saving the managed user, post the Image to an Upload action on the ImageHandler (have a look at this article). This action must return the new Id of the image. After you've received the new Id, update the User.ImageId on client side and call SaveChanges on breeze.

DatePicker.Value.Set Error binding to datasource

I have a bindingsource control called binding, on a form in VS2012, and a DateTimePicker control bound to it.
for the binding properties I have MinDate = 1/01/1753 and MaxDate = 31/12/9998
Value has been set by picking Today from the calender 5/04/2013 11:27 AM
I set a bindingsource up using
var dset = base.Context.ContactEvents;
var qry = dset.Where(p => p.Id > 0).OrderBy(x => x.Id);
qry.Load();
this.bindingSource.DataSource = dset.Local.ToBindingList();
The bindingsource is used in the following manner;
public void RefreshBindingDataSourceAndPosition(BindingSource binding)
{
binding.DataSource = this.bindingSource.DataSource; // error raised here
binding.Position = this.bindingSource.Position;
}
The error information is
System.ArgumentOutOfRangeException crossed a native/managed boundary
HResult=-2146233086
Message=Value of '1/01/0001 12:00:00 AM' is not valid for 'Value'. 'Value' should be between 'MinDate' and 'MaxDate'.
Parameter name: Value
Source=System.Windows.Forms
ParamName=Value
StackTrace:
at System.Windows.Forms.DateTimePicker.set_Value(DateTime value)
InnerException:
I can work around the problem by not binding the Data Picker , and setting it in the EventsBindingSource_CurrentChanged event
However it seems odd to have to do this. How can I get the databinding working?
[Update]
This problem is similar to the one described here
I have tried to reproduce the problem in a simpler project so as to try and isolate the cause, however it works in the simpler project. Also the project works on another computer.
The problem occurs on my computer with both SQL Server 2012 and 2008R2. I have tried altering the date format and country in control panel. Also I have tried different settings for the format property. I have also tried setting the date field to support null.
When I copy the error to the clipboard it shows the following ;
System.Reflection.TargetInvocationException occurred
HResult=-2146232828
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
InnerException: System.ArgumentOutOfRangeException
HResult=-2146233086
Message=Value of '1/01/0001 12:00:00 AM' is not valid for 'Value'. 'Value' should be between 'MinDate' and 'MaxDate'.
Parameter name: Value
Source=System.Windows.Forms
ParamName=Value
StackTrace:
at System.Windows.Forms.DateTimePicker.set_Value(DateTime value)
InnerException:
My EF class is as follows
public class ContactEvent : LoggedEntity
{
public virtual SortableBindingList<ContactEventAttendee> Attendees { get; private set; }
public virtual ContactEventType ContactEventType { get; set; }
public string Details { get; set; }
public DateTime? EventTime { get; set; }
public virtual SortableBindingList<ContactEventItem> Items { get; private set; }
public int State { get; set; }
public string Title { get; set; }
public override string ToString()
{
return "Contact Events";
}
}
it inherits from
public abstract class LoggedEntity
{
public LoggedEntity()
{
this.RowId = Guid.NewGuid();
this.RowVersionId = 0;
AppDomain dm = AppDomain.CurrentDomain; // Gets the current application domain for the current Thread.
object s = AppDomain.CurrentDomain.GetData("SiteNumber");
this.SourceSiteNumber = Convert.ToInt32(s);
}
public LoggedEntity(int SiteNumber)
{
// the following 3 are used to identify the version
this.RowId = Guid.NewGuid();
this.RowVersionId = 0;
this.SourceSiteNumber = SiteNumber;
}
public int Id { get; set; }
public Guid RowId { get; set; }
[ConcurrencyCheck]
public int RowVersionId { get; set; }
public int SourceSiteNumber { get; set; }
}
[update]
A similar problem is here
[update]
Another here makes me think I need to look at how keys are being processed.
[update]
I noticed the following in the output window
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll
[update]
This led me to
here
and after turning on the debug options I found an error
Invalid object name 'dbo.__MigrationHistory'.
however that is a known bug in EF5
[Update]: I found another person with similar unsolved issues here
Discovered I dont have problems when running the .EXE
[update] I can skip over the error by disabling "Break when exceptions cross App Domain or managed/native boundary
in Tools->Options->Debugging->General
[update] I adding the following, so I could inspect the control properties.
private void EventsBindingSource_BindingComplete(object sender, BindingCompleteEventArgs e)
{
// If the BindingComplete state is anything other than success,
// set the ErrorProvider to the error message.
if (e.BindingCompleteState != BindingCompleteState.Success)
{
errorProvider1.SetError((Control)e.Binding.BindableComponent, e.ErrorText);
var errdesc = e.ErrorText;
var ctrl = (Control)e.Binding.BindableComponent;
var info = string.Format(
"{0} {1}",errdesc,
ctrl.ToString());
Debug.Print(info);
// "Value of '1/1/0001 12:00:00 AM' is not valid for 'Value'.
'Value' should be between 'MinDate' and 'MaxDate'.\r\nParameter name:
Value System.Windows.Forms.DateTimePicker, Value: 1/1/1900 12:00:00 AM"
}
else
{
errorProvider1.SetError((Control)e.Binding.BindableComponent, "");
}
}
The cause of the exception may be that the DatePicker's DataBinding "Value" property has been set to a BindingSource field.
Only the DatePicker's DataBinding "Text" property needs to be set for the data binding to work correctly.
Check if there is a value in the DatePicker's DataBinding "Value" property field, once removed the issue should go away.
It seems that the key problem is the property is a Nullable DateTime. Probably the null value used to transcribe the DateTimePicker component is '1 / 01/0001 12:00:00 AM 'which creates a problem related to the configuration of MinValue and MaxValue. Using the Advanced tab of the DataBinding has an option to set the value to be used to null One way to solve this would be setting the value to null as MinDate, or we can set the MinDate with the value '01 / 01/0001 12:00 : 00 AM '. Despite my limited experience, I believe that this may be the source of your problems. the link http://msdn.microsoft.com/en-us/library/aa480734.aspx can see something else on the Advanced tab of the property DataBinding.

Intermittent Validation Problems using ServiceSttack

I'm using ServiceStack to build an API and at the same time, I'm using the plugin that allows Razor views to return html to browsers.
I have validation set up and configured correctly. I know this because I get the validation messages on the corresponding Razor view and the messages are accurate. However, if I modify the Razor view at all (and by "at all" I mean something as simple as adding a line break and then immediately deleting it), I get a 500 error accompanied by a blank page.
Other times, while in the process of simply refreshing the page to review styling of the Razor view, the validation simply returns a blank page with the same non-useful 500 error. And of course, if I remove the validation, the Razor view renders just fine 100% of the time.
What must I do to have validation working at all times? My code is straight forward and matches everything that I've been able to read in the Docs. Namely, both the response and the requests are in the same namespace and the validator is coded to the request.
Here is the request DTO
namespace MyServer.DTO
{
[Validator(typeof(SignUpValidator))]
[Route("SignUp")]
public class SignUp : IReturn<SignUpResponse>
{
public string UserName { get; set; }
public string Email { get; set; }
public string EmailConfirm { get; set; }
public string Password { get; set; }
public string PasswordConfirm { get; set; }
public int UserId { get; set; }
}
}
Here is the corresponding validator
namespace MyServer.DTO
{
public class SignUpValidator : AbstractValidator<SignUp>
{
public SignUpValidator()
{
RuleSet(ApplyTo.Post, () =>
{
RuleFor(e => e.UserName).NotEmpty();
RuleFor(e => e.Email).NotEmpty();
RuleFor(e => e.EmailConfirm).NotEmpty();
RuleFor(e => e.Password).NotEmpty();
RuleFor(e => e.PasswordConfirm).NotEmpty();
}
);
}
}
}
Here is the response
namespace MyServer.DTO
{
public class SignUpResponse
{
bool DidSucceed { get; set; }
int NewUserId { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
}
And lastly, here is the code that configures the validation plugin
Plugins.Add(new ValidationFeature());
Container.RegisterValidators(typeof(SignUpService).Assembly);
As you can see, everything is pretty vanilla and by the book, but this setup is very fragile for some reason. Any modification to the corresponding Razor view and I get the aforementioned errors. Then I have to recompile repeatedly until it works again.
I should also mention that, if I use the REST Console (google chrome extension thingy) to test this, I get the following results when posting to the exact same URI:
Content-Type set to : application/json - Everything works as intended. 400 Response with the errors listed in the response body.
Content-Type set to : application/html - Consistently breaks. 500 Response with no data in the response body.
There must be something that I'm missing.
Thanks so much for your time and I would appreciate any help.
Thanks again.

Resources