Hoping someone can point me in the right direction
Using DevExpress ASPxGridView and the Edit form.
I need to 'interrupt' the RowInserting events to warn the user if there's already a record matching their information and allow them to continue or cancel.
I've added the check (and a cancel) to the OnRowInserting event and am using customJSProperties to trigger the popup on the callback.
But I'm stuck on how to get the popups 'yes' button to resume (or restart) the Row Insert.
Is there a way of triggering the editform update event again from client side code?
Or do I need a completely different approach?
First of all, I found this article Use "yes" / "no" in edit mode for boolean value
Second of all, I hope your all rows has a unique value like ID. If so, I sugget a way like this;
Use OnRowInserting function of ASPxGridview. (Find here code examples etc.)
Check your inserting ID is already in your data store or not. (With running a query)
If in your data store or not, use XtraMessageBox like;
XtraMessageBox.Show(“Content”, “Title”, MessageBoxButtons.YesNo);
before that, add DevExpress.XtraEditors namespace. Then you can use it like;
DialogResult myDialogResult;
myDialogResult = XtraMessageBox.Show("Content", "Title", MessageBoxButtons.YesNo);
if (myDialogResult == DialogResult.Yes)
{
//yes was clicked
}
if (myDialogResult == DialogResult.No)
{
//no was clicked
}
Hope it gives you an idea. And If you have Devexpress Licence, you can ask in Devexpress Support. They are really quick and helpful.
You can solve this with custom HttpHandler. Something like this:
press Save button on your edit form
Save initiates httphandler call (from javascript) with data needed for validation (tablename, id). With jquery you can call http handler like this:
if handler returns true continue with save, otherwise show alert with OK/Cancel
if user chooses OK continue with Save
Javascript call with http handler would look like this:
$.ajax({
async: false,
cache: false,
url: 'YourHttpHandler.ashx',
data: { tableName: "your table name", record_id: your_id },
success:
function (data, textStatus, xmlHttpRequest)
{
if(data.result==true)
if(confirm('Continue?'))
{
// continue with save
}
}
});
Related
In this page I have put plsql code on click of Create Assignment button. There is a constraint on column "Assigned To" which usualy fires when that field left blank.
I want to put a validation so that I can get my own alert message which should be user readable. Also after that message submit process should be ignored.
I tried with field name :P11_Assignment NULL in the condition of PLSQL code in Dynamic Action but it is not working.
Please advise with a solution.
Before the PL/SQL Action add an Execute Javascript action.
You will want to use apex.message.* function like the following:
apex.message.clearErrors
apex.message.showErrors
Oracle Documentation link
Example:
apex.message.clearErrors();
if ($v("P11_Assignment").trim() == '') {
apex.message.showErrors({
type: "error",
location: [ "page", "inline" ],
pageItem: "P11_Assignment",
message: 'Must have a Value',
unsafe: false
});
return false; /* This is important, it stops the next action(s) from running. */
}
putting IF ELSE condition in the begining of plsql code
IF field is empty THEN don't execute the plsql code and change the field item to a value.
On value change of that item put an alert message in Dynamic Action.
I have a method that checks for all unread messages belonging to a user. When the app loads, this number appears next to the "Messages" drop down. In Meteor, how would I update this count or variable for when a new message comes in or when the user reads an unread message? Pretty much I needs the method to send down the new count anytime a message status changes without refreshing the app itself.
I'm familiar with the Tracker.autorun functionality but I don't think it'll help with this situation. What's the best practice for approaching this?
Use Publish/Subscribe. It is always reactive. If you do not want to have all unread messages sent to the client straight away and counted there, you create a custom collection that justs count the number of unread messages and publishes that count. Look at the example a bit down in the linked page that starts with
// server: publish the current size of a collection
This is exactly your use case.
I have exactly this setup for new messages. In my header I have:
<li>Messages <span class="counter">{{Messages.count}}</span></li>
And then I have a helper that returns the cursor:
Template.header.helpers({
Messages: function(){ return Messages.find(); }
});
In the old days, before David Weldon set me straight I used to have a helper to return the count, now I just refer to the count directly in the blaze html template.
Now, in this approach I'm subscribing to the Messages collection so that new messages are transmitted to the client and can then be counted locally. This is on the assumption that they are going to be read soon. If you want to avoid this step then you should probably publish a Stats collection or include a stats key in the user object so that just the count itself can be synced via pub-sub.
You can just have a field like read, and update like:
Method for marking one message as read:
markRead: function(messageId){
Messages.update(messageId, {
$set: {
read: true //this needs to be set to false when its inserted
}
})
}
Bulk update method (assuming all messages have receiverId saved):
markAllRead: function(){
Messages.update({receiver: Meteor.userId(), read:false}, {
$set: {
read: true
}
}, {multi: true})
}
You can count read:false ones to retrieve count and you don't have to write anything else
Helper:
count: function(){
//even if your publish/subscribe is correct, the count we want is from messages that are not read and the receiver is current user.
return Messages.find({receiver: Meteor.userId(), read: false }).count();
}
Event:
'click .elementClass': function(){
//both users see the messages and they can both click. We want to update the right message for the right user. Otherwise, the other user can mark the message as read when the receiver is the other user which they shouldn't be able to do. You can do a simple check on the client side, and another check in the method if necessary.
if(this.receiver === Meteor.userId()){
Meteor.call('markAsRead', this._id)
}
}
Let me know if it solves your problem/answers all your questions.
I'm in the process of learning meteor. I followed the tutorial to create microscope. If some one submits a post meteor will re render the template for all users. This could be very annoying if there are hundreds of posts then the user will come back to the top of the page and loose track of where he was. I want to implement something similar to what facebook has. When a new post is submitted template isn't rendered rather, a button or link will appear. Clicking it will cause the template to re-render and show the new posts.
I was thinking of using observeChanges on the collection to detect any changes and it does stop the page from showing new posts but only way to show them is to reload the page.
Meteor.publish('posts', function(options) {
var self = this, postHandle = null;
var initializing = true;
postHandle = Posts.find({}, options).observeChanges({
added: function(id, post) {
if (initializing){
self.added('posts', id, post);
}
},
changed: function(id, fields) {
self.changed('posts', id, fields);
}
});
self.ready();
initializing = false;
self.onStop(function() { postHandle.stop(); });
});
Is this the right path to take? If yes, how do I alert the user of new posts? Else, what would be a better way to implement this?
Thank you
This is a tricky question but also valuable as it pertains to a design pattern that is applicable in many instances. One of the key aspects is wanting to know that there is new data but not wanting to show it (yet) to the user. We can also assume that when the user does want to see the data, they probably don't want to wait for it to be loaded into the client (just like Facebook). This means that the client still needs to cache the data as it arrives, just not display it immediately.
Therefore, you probably don't want to restrict the data displayed in the publication - because this won't send the data to the client. Rather, you want to send all the (relevant) data to the client and cache it there until it is ready.
The easiest way involves having a timestamp in your data to work from. You can then couple this with a Reactive Variable to only add new documents to your displayed set when that Reactive Variable changes. Something like this (code will probably be in different files):
// Within the template where you want to show your data
Template.myTemplate.onCreated(function() {
var self = this;
var options = null; // Define non-time options
// Subscribe to the data so everything is loaded into the client
// Include relevant options to limit data but exclude timestamps
self.subscribe("posts", options);
// Create and initialise a reactive variable with the current date
self.loadedTime = new ReactiveVar(new Date());
// Create a reactive variable to see when new data is available
// Create an autorun for whenever the subscription changes ready() state
// Ignore the first run as ready() should be false
// Subsequent false values indicate new data is arriving
self.newData = new ReactiveVar(false);
self.autorun(function(computation) {
if(!computation.firstRun) {
if(!self.subscriptionsReady()) {
self.newData.set(true);
}
}
});
});
// Fetch the relevant data from that subscribed (cached) within the client
// Assume this will be within the template helper
// Use the value (get()) of the Reactive Variable
Template.myTemplate.helpers({
displayedPosts = function() {
return Posts.find({timestamp: {$lt: Template.instance().loadedTime.get()}});
},
// Second helper to determine whether or not new data is available
// Can be used in the template to notify the user
newData = function() {
return Template.instance().newData.get();
});
// Update the Reactive Variable to the current time
// Assume this takes place within the template helper
// Assume you have button (or similar) with a "reload" class
Template.myTemplate.events({
'click .reLoad' = function(event, template) {
template.loadedTime.set(new Date());
}
});
I think this is the simplest pattern to cover all of the points you raise. It gets more complicated if you don't have a timestamp, you have multiple subscriptions (then need to use the subscription handles) etc. Hope this helps!
As Duncan said in his answer, ReactiveVar is the way to go. I've actually implemented a simple facebook feed page with meteor where I display the public posts from a certain page. I use infinite scroll to keep adding posts to the bottom of the page and store them in a ReactiveVar. Check the sources on github here and the live demo here. Hope it helps!
I have an app where you can choose (or add if they don't exist!) a superhero/villain character from a certain universe on the first page; then outfit him with weapons, clothes, and gadgets on the second page (build).
I have this route defined:
Router.route('/build/:character', {
name: 'build'
waitOn: Meteor.subscribe('characters', {name: this.params.character})
//and a few other subscriptions and sessions as well for the items
//and stuff, but those don't matter here.
}
The link from the specific character, though, passes along a query as well:
<a href="{{pathFor 'build' query=this.universe}}">
So the final link could look something like this:
/build/Aquaman?DCComics
Now the page you are on will display a list of weapons and gadgets where you could also add other stuff if you so wish. Then you are supposed to drag the items you want to include onto your version of this hero.
Problem is, at this point the app doesn't know you even want to create your own hero. Maybe the user is just looking through them for fun. There's a button that the user has to click first to initialize the creating process, and that's when the actual _id is created, something like this:
Meteor.methods({
buildHero: function(heroCharacterName, heroUniverse) {
var heroToAdd = {}
heroToAdd['characterName'] = heroCharacterName
heroToAdd['universe'] = heroUniverse
heroToAdd['_createdAt'] = new Date()
CreatedHeroes.insert(heroToAdd, function() {
if (! error)
//Update the subscription somehow...
})
}
})
So, the _id that is created here in the new Collection must be passed along to a subscription somehow, because I don't want the user to see other personal heroes that have been created, only his own newly created one.
The solution I have in mind is adding the _id onto the URL in form of a hastag, and use this.params.hash in the subscription like so:
Router.route('/build/:character', {
name: 'build'
waitOn: [Meteor.subscribe('characters', {name: this.params.character}),
Meteor.subscribe('createdheroes', this.params.hash)]
}
First of all, is this a valid approach? If so, how do I accomplish it; how do I actually update the URL to include this hash?
If not, what would be a better approach?
I think you have to handle this logic in the data context or in a template helper and not in the way of subscribing/publishing.
If I was you I would besure that the newly created item is being published and subscribed by the client and modify your search query just that it only adds the newly created item.
I am not sure if I understand your question well but what I got, you will know the last _id which was used on your insert.
Instead of letting done this automatically by meteor, just use the meteor method to create / get that _id value >> see Meteor Documentation
var new_id = new Mongo.ObjectID()
col1.insert({ _id: new_id, ... });
col2.insert({ ..., ref_col1_id: new_id, ... });
I have a mysql database with the tables "deliverables", "tags" and "deliverables_has_tags". I want to link tags to a deliverable.
This is what I do in my javascript file:
<script type="text/javascript" language="javascript">
$(function () {
var object = {};
$.ajax({
type: "GET",
url: "/Deliverable/Tags",
dataType: "json",
success: function (data) {
object.tags = data;
}
});
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data("ui-autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function (request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
object.tags, extractLast(request.term)));
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
</script>
I can add multiple tags in my textbox.
But now I want to save this in my repository.
In my Action method in controller:
repository.AddDeliverable(model.Title, model.Description, model.UsernameID, data, datatwo, model.VideoUrl, model.AfstudeerrichtingID, model.ProjectID);
Tags action:
public JsonResult Tags()
{
var data = (repository.GetTags()).ToArray();
return Json(data, JsonRequestBehavior.AllowGet);
}
In my repository:
public IQueryable<string> GetTags()
{
return from tag in entities.tags
orderby tag.tag_name
select tag.tag_name;
}
I have no clue how to save this in my database.
Can anybody help me?
If I correctly understood your question, you have implemented your tag handling as follows:
There is MVC action method that returns the view with input placeholder containing no data
The placeholder itself is probably input type=text with id=tags
On 'dom ready' you fire ajax request to retrieve your tags from database, json-serialized as array; when it arrives you store it to tags variable (no error handling(!))
At the same time you decorate your input with jqueryui autocomplete that reacts on user input and returns items from the tags variable
Since input already contains tags (comma separated), your filter is first letters of the last tag
So, you have a situation when user has input a few comma separated tags (probably some of them can be new) and now wants to save it to the database. For each input, if that is a known tag you have to store it to "deliverables_has_tags". If there is a new tag, you have to store it both to "tags" and "deliverables_has_tags".
Most common scenario would be having a 'Save' button to start saving process.
Let's analyze what you have to do in the process.
1) Button click
On button click you use js to convert your comma separated tags string
using logic like split(term) to the array, and serialize it. You can
do serialization using serializeArray and manually create JSON
object, or serialize the whole form using
$('#yourForm').serialize(). I would choose the first option
because that way I get more control over JSON format and avoid
problems with MVC default model binder.
2) Ajax call
When the JSON object is ready to be sent, you fire an ajax POST
request to your MVC POST action method. When you save state always
avoid GET because new versions of browsers can scan thru your page and
actively preload urls using GET requests. You don't want this here. Of
course, use your data as a data-parameter in the ajax call.
3) Action method
When the request arrives, you have to process it in your controller
using a new action method. Typically in this case you will have
something like public JsonResult SaveTags(SaveTagsModel saveTags) {
... } which saves tags using your repository and returns result that
says something like 'OK' or 'ERROR' (sth like
response.isSaved=true/false). Tricky part can be designing view model
according to your JSON object - this could help. And regarding
collections this could be valuable info.
When saving, use transaction to ensure everything is saved at once.
First check if each tag exists in the database and insert those who
don't exist. After that, check for each tag if there is appropriate
n-n relation in deliverables_has_tags and insert it if there isn't.
I believe that you should use same repository encapsulation for both
operations.
In the post action, include FormCollection collection as argument and gather your tags from that. There is no automatic way. You could implement some custom model binding, but that is probably not worth the effort.