KRL - How do you get the value of a watched field? - krl

I am watching a field on a page with a change.
watch("#searchbox","change");
How do you get the new value of the field in the rule that fires after it changes?
I have a rule like this
rule get_update is active {
select when web change "#searchbox"
....
}
I cannot find out how to get the new value. I cannot use watch it with a submit.
Thanks

I am going to guess what I think you are trying to do:
You have an input on a page and when a user types in the input, you want to be able to raise an event and get the new value from the input that the user was typing into so you can react to what ever it is that they typed in.
Based on the assumptions I have made:
The watch action is not what you really want to use because it only raises an event on the action that it is watching and doesn't send any other data along with the event. You will want to write some of your own custom JavaScript to
watch for the user typing
get the new value from the input
raise web event with the new value as a parameter
Here is some sample code taken from http://kynetxappaday.wordpress.com/2010/12/16/day-8-raise-web-events-from-javascript/ that illustrates raising a web event with a parameter in JavaScript
ruleset a60x488 {
meta {
name "raising-custom-web-events"
description <<
raising-custom-web-events
>>
author "Mike Grace"
logging on
}
rule run_on_a_pageview {
select when pageview ".*"
{
notify("Hello","I ran on a pageview") with sticky = true;
emit <|
app = KOBJ.get_application("a60x488");
app.raise_event("custom_event_just_for_me", {"answer":42});
|>;
}
}
rule respond_to_custom_event_raised_from_emitted_js {
select when web custom_event_just_for_me
pre {
answer = event:param("answer");
}
{
notify("What is the answer?",answer) with sticky = true;
}
}
}

Related

Mark an order as "Full Payment" on Sage 200

I am inserting orders on Sage 200 through an application using the client side, C# and APIs.
I would like to check the "Full payment" checkbox on the "Payment with order" tab.
Currently, I am setting the PaymentType property, which is not working.
order.PaymentType = Sage.Accounting.SOP.SOPOrderPaymentTypeEnum.EnumSOPOrderPaymentTypeFull;
order is an instance of Sage.Accounting.SOP.SOPOrder.
Do you know how I can check that property?
The following method should supply the required results.
private static void SetPaymentWithOrder(Sage.Accounting.SOP.SOPOrder sopOrder)
{
// Indicate that order has payment
sopOrder.PaymentWithOrder = true;
// This is full payment order
sopOrder.PaymentType = Sage.Accounting.SOP.SOPOrderPaymentTypeEnum.EnumSOPOrderPaymentTypeFull;
// Fetch the the Payment Methods. SOPPaymentMethods contructor accepts the boolean flag whether to fetch payment methods including card processing method or not.
Sage.Accounting.SOP.SOPPaymentMethods paymentMethodsCollection = new Sage.Accounting.SOP.SOPPaymentMethods(false);
// Set the first payment method of the collection to the order
sopOrder.PaymentMethod = paymentMethodsCollection.First;
}
dont know if you ever managed to figure this one out or not.
Not sure if you knew this, but you cannot modify the Sales Order on the view form, or at least shouldn't be trying to do so.
Using either of the Enter/Amend Sales Order forms will allow you to do so.
What is potentially happening, is that the properties that the controls are bound to are not updating the UI after your code has run.
You can simply force this to happen using the following
Fetching the underlying bound object
public Sage.Accounting.SOP.SOPOrderReturn SOPOrderReturn
{
get
{
//Loop over the boundobjects collection
//check if the bound object is of the type we want - e.g. SOPOrderReturn
//if correct type, return this object
Sage.Common.Collections.BoundObjectCollection boundObjects = this.form.BoundObjects;
if (boundObjects != null)
{
foreach (object boundObject in boundObjects)
{
if (boundObject is Sage.Accounting.SOP.SOPOrderReturn)
{
this._sopOrderReturn = boundObject as Sage.Accounting.SOP.SOPOrderReturn;
break;
}
}
}
return this._sopOrderReturn;
}
}
Fetch the correct underlying form type that the amendable form is, suspending the databinding,
perform your changes,
resuming the databinding
Sage.MMS.SOP.MaintainOrderForm maintainOrderForm = this.form.UnderlyingControl as Sage.MMS.SOP.MaintainOrderForm;
maintainOrderForm.BindingContext[this.SOPOrderReturn].SuspendBinding();
this.SOPOrderReturn.PaymentWithOrder = true;
this.SOPOrderReturn.PaymentType = Sage.Accounting.SOP.SOPOrderPaymentTypeEnum.EnumSOPOrderPaymentTypeFull;
maintainOrderForm.BindingContext[this.SOPOrderReturn].ResumeBinding();
should do the trick.

Updating MongoDB in Meteor Router Filter Methods

I am currently trying to log user page views in meteor app by storing the userId, Meteor.Router.page() and timestamp when a user clicks on other pages.
//userlog.js
Meteor.methods({
createLog: function(page){
var timeStamp = Meteor.user().lastActionTimestamp;
//Set variable to store validation if user is logging in
var hasLoggedIn = false;
//Checks if lastActionTimestamp of user is more than an hour ago
if(moment(new Date().getTime()).diff(moment(timeStamp), 'hours') >= 1){
hasLoggedIn = true;
}
console.log("this ran");
var log = {
submitted: new Date().getTime(),
userId: Meteor.userId(),
page: page,
login: hasLoggedIn
}
var logId = Userlogs.insert(log);
Meteor.users.update(Meteor.userId(), {$set: {lastActionTimestamp: log.submitted}});
return logId;
}
});
//router.js This method runs on a filter on every page
'checkLoginStatus': function(page) {
if(Meteor.userId()){
//Logs the page that the user has switched to
Meteor.call('createLog', page);
return page;
}else if(Meteor.loggingIn()) {
return 'loading';
}else {
return 'loginPage';
}
}
However this does not work and it ends up with a recursive creation of userlogs. I believe that this is due to the fact that i did a Collection.find in a router filter method. Does anyone have a work around for this issue?
When you're updating Meteor.users and setting lastActionTimestamp, Meteor.user will be updated and send the invalidation signal to all reactive contexts which depend on it. If Meteor.user is used in a filter, then that filter and all consecutive ones, including checkLoginStatus will rerun, causing a loop.
Best practices that I've found:
Avoid using reactive data sources as much as possible within filters.
Use Meteor.userId() where possible instead of Meteor.user()._id because the former will not trigger an invalidation when an attribute of the user object changes.
Order your filters so that they run with the most frequently updated reactive data source first. For example, if you have a trackPage filter that requires a user, let it run after another filter called requireUser so that you are certain you have a user before you track. Otherwise if you'd track first, check user second then when Meteor.logginIn changes from false to true, you'd track the page again.
This is the main reason we switched to meteor-mini-pages instead of Meteor-Router because it handles reactive data sources much easier. A filter can redirect, and it can stop() the router from running, etc.
Lastly, cmather and others are working on a new router which is a merger of mini-pages and Meteor.Router. It will be called Iron Router and I recommend using it once it's out!

KRL: Pragmatically access current ruleset id

How do I get the name of the current ruleset in a KRL rule? I find that I often write
notify("a421x70","Your Message Here") with sticky = true;
but when I copy the ruleset I have to go through and change the "a421x70" part. It would be so much better to have the current ruleset in a variable and use that in my notify() action.
In the pre block of a rule you can
rid = meta:rid();
http://docs.kynetx.com/docs/Meta_Info
Example:
ruleset a60x598 {
meta {
name "appid tester"
description <<
getting app rid pragmatically
>>
author "Michael Grace"
logging off
}
rule get_rid_rule {
select when web pageview ".*"
pre {
rid = meta:rid();
}
{
notify("Current App rid is", "#{rid}") with sticky = true;
}
}
}

How do I clear one set of errors on a two form page in zend

I have a one page website that has two seperate forms that need to be posted back to the same page, the problem being, that if I submit one form, the error checking is done on both, so displays error messages for both. What I need is that if form one is submit, only form ones' error messages appear, and not form twos. Is this possible in zend?
It isn't a problem for zend to do - but it is a problem for you to solve!
If you give your form a hidden field, or if you have a field ID unique to one form, you should be able to check which form has been submitted in your controller, then you tell zend which form you want it to check. Something like the following should do the job, it will check for a field with the ID unique_form_one_field which obviously should only be on form one, this could be a hidden field for example:
// Get the forms:
$form1 = $this->_helper->formLoader('form_one');
$form2 = $this->_helper->formLoader('form_two');
// Check if there is a POST:
if (!$request->isPost())
{
// It isn't show the forms:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// It is, get the POST data:
$post_data = $request->getPost();
// Check if form one has been submitted:
if (isset($post_data['unique_form_one_field']))
{
// Check if form one is valid:
if (!$form1->isValid($post_data))
{
// Its got an error, display the forms again, form one will now be populated with the data and also the error messages:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// Form one was valid - do what you want to process it:
}
}
else
{
// Check if form two is valid:
if (!$form2->isValid($post_data))
{
// Its got an error, display the forms again, form two will now be populated with the data and also the error messages:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// Form two was valid - do what you want to process it:
}
}
}

Change in URL to trigger Event in GWT

I am iterating through some data and generating parameterized URL links based on some conditions like this:
finishedHTML.append("<a href=\"http://" + domain + "&service=" + allEvents[eventCounter].EventService +"&day="+ offSet+(-1 * i) +"\"><img src=\"/info.jpg\" alt=\"Info\"/>");
I had the beginning of my application checking for URL parameters when the page was loaded/refreshed, and take some action depending on if the parameters were there and what they were.
However, I added a # to the beginning of the paramters, so the page wouldn't need to be refreshed, but now it's not triggering the function that checks the URL.
My question is how can I trigger an event in GWT when a user clicks a link? Do I need to generate GWT controls, and link a click handler? Is it possible to setup an event that fires when the URL is changed???
UPDATE:
Adam answered part of the initial question, but I can't get the querystring after "#". Is there a better way than the function below:
public static String getQueryString()
{
return Window.Location.getQueryString();
}
In other words, if I enter example.com?service=1 I get service=1 as my querystring. If I enter example.com#?service=1, I get a null value for the querystring..
Use History.addValueChangeHandler( handler ), and create a handler to catch the URL changes.
There's no need for click handlers etc., any change of the "hash" part in the URL will be sufficient.
EDIT:
See this code example - it will parse URLs of the form http://mydomain/my/path#tok1&tok2&tok3
public void onValueChange(ValueChangeEvent<String> event) {
String hash = event.getValue();
if ( hash.length() == 0 ) {
return;
}
String[] historyTokens = hash.split("&",0);
// do stuff according to tokens
}
(Just responding to your Update)
Have you tried
History.getToken()
to get the value after the "#"?