Author | Topic: Using fieldblock as a datalink | |
---|---|---|
Scott Krise | Using fieldblock as a datalink on Fri, 20 Oct 2006 11:04:31 -0400 I am converting a text based data entry screen to a GUI screen, and I am flip-flopping between setting the datalink for my entry field as a variable (like I did in clipper), or to tie it directly to a database field using a fieldblock. I am using the tdxget function from top-down to do my gets, and I can see definite advantages to using fieldblocks, however I am running into one specific problem doing it that way. If the I use the fieldblock logic and start to ADD a record to the table, one of my first steps in the ADD button logic is to do a dbappend()...which of course adds a blank record to my table. If the user updates the information and clicks my SAVE button....I'm good...If they decide not to update and hit my CANCEL button to exit without saving...I'm good (I just delete the blank record they created), however if something unusual happens and they do an END TASK of my application from the task manager, then I am stuck with that blank record being left out in my table. If I stick with using varibles as the datalink for my gets, I avoid this problem, because I do the dbappend immediately before writing the variables to the table, so this problem will never occur. I guess I'm wanting some opinions on how everyone deals with this in their apps. Thanks, Scott | |
Rodd Graham | Re: Using fieldblock as a datalink on Fri, 20 Oct 2006 13:04:55 -0500 Scott, While I personally do something completely different, your strategy can be altered as follows: ADD: append blank delete dbcommit() SAVE: recall unlock CANCEL: unlock Rodd "Scott Krise" <dstine_cti@alltel.net> wrote in message news:78f1c6b9$69578232$840f1@news.alaska-software.com... >I am converting a text based data entry screen to a GUI screen, and I am >flip-flopping between setting the datalink for my entry field as a variable >(like I did in clipper), or to tie it directly to a database field using a >fieldblock. I am using the tdxget function from top-down to do my gets, and >I can see definite advantages to using fieldblocks, however I am running >into one specific problem doing it that way. If the I use the fieldblock >logic and start to ADD a record to the table, one of my first steps in the >ADD button logic is to do a dbappend()...which of course adds a blank >record to my table. If the user updates the information and clicks my SAVE >button....I'm good...If they decide not to update and hit my CANCEL button >to exit without saving...I'm good (I just delete the blank record they >created), however if something unusual happens and they do an END TASK of >my application from the task manager, then I am stuck with that blank >record being left out in my table. > > If I stick with using varibles as the datalink for my gets, I avoid this > problem, because I do the dbappend immediately before writing the > variables to the table, so this problem will never occur. > > I guess I'm wanting some opinions on how everyone deals with this in their > apps. > > Thanks, > > Scott > > > | |
James Loughner | Re: Using fieldblock as a datalink on Fri, 20 Oct 2006 15:31:28 -0400 I don't do the append until I hit the save button. To init the screen to a new record I do DBGoBottom(), skip(1) then read the phantom record into the screen. I do all in class code (generated from the FD) so I have three methods I almost always use and 1 ivar the ivar is ::EditType which can normally be "EDIT" or "NEW" the methods are ::RefreshWND, ::Validate, and ::Save METHOD RrefreshWND() IF ::EditType = "NEW" (::DBarea)->(DBGoBottom()) (::DBarea)->(DBSkip()) AEval( ::edControls, {|o| o:setData() } ) read data into screen ...... ELSE AEval( ::edControls, {|o| o:setData() } ) read data into screen ..... ENDIF RETURN Self METHOD Save() IF ::Validate() IF (::DbArea)->(DBSeek(keyvalue)) (::DbArea)->(DBRLock()) ELSE (::DbArea)->(DBAppend()) ENDIF AEval( ::edControls, {|o| o:getData() } ) save data from screen .... ::Destroy() ENDIF RETURN Self note ::edControls is an array with reference to all XBPs that have a Datalink assigned Jim Scott Krise wrote: > I am converting a text based data entry screen to a GUI screen, and I am > flip-flopping between setting the datalink for my entry field as a variable > (like I did in clipper), or to tie it directly to a database field using a > fieldblock. I am using the tdxget function from top-down to do my gets, and > I can see definite advantages to using fieldblocks, however I am running > into one specific problem doing it that way. If the I use the fieldblock > logic and start to ADD a record to the table, one of my first steps in the > ADD button logic is to do a dbappend()...which of course adds a blank record > to my table. If the user updates the information and clicks my SAVE > button....I'm good...If they decide not to update and hit my CANCEL button > to exit without saving...I'm good (I just delete the blank record they > created), however if something unusual happens and they do an END TASK of my > application from the task manager, then I am stuck with that blank record > being left out in my table. > > If I stick with using varibles as the datalink for my gets, I avoid this > problem, because I do the dbappend immediately before writing the variables > to the table, so this problem will never occur. > > I guess I'm wanting some opinions on how everyone deals with this in their > apps. > > Thanks, > > Scott > > > | |
Scott Krise | Re: Using fieldblock as a datalink on Thu, 26 Oct 2006 08:24:20 -0400 Jim, Thanks...this is what I was looking for. Actually, I tried this approach earlier...but ran into some problems with it. It's working the way I want it to now...I think I had another issue that caused my problems before. Thanks for your input (as well as the others who replied). Scott | |
Joe Carrick | Re: Using fieldblock as a datalink on Sat, 21 Oct 2006 09:27:08 -0700 I use fieldWBlock() instead. It's better because it identifies the work area and allows for the possibility that the current work area is not the one you are linking the data to. -Joe Scott Krise wrote: > I am converting a text based data entry screen to a GUI screen, and I am > flip-flopping between setting the datalink for my entry field as a variable > (like I did in clipper), or to tie it directly to a database field using a > fieldblock. I am using the tdxget function from top-down to do my gets, and > I can see definite advantages to using fieldblocks, however I am running > into one specific problem doing it that way. If the I use the fieldblock > logic and start to ADD a record to the table, one of my first steps in the > ADD button logic is to do a dbappend()...which of course adds a blank record > to my table. If the user updates the information and clicks my SAVE > button....I'm good...If they decide not to update and hit my CANCEL button > to exit without saving...I'm good (I just delete the blank record they > created), however if something unusual happens and they do an END TASK of my > application from the task manager, then I am stuck with that blank record > being left out in my table. > > If I stick with using varibles as the datalink for my gets, I avoid this > problem, because I do the dbappend immediately before writing the variables > to the table, so this problem will never occur. > > I guess I'm wanting some opinions on how everyone deals with this in their > apps. > > Thanks, > > Scott > > > | |
Garry Allen | Re: Using fieldblock as a datalink on Thu, 26 Oct 2006 13:09:36 -0400 Hi Scott I (still) use variables for several reasons. The main one is that everything I do is class based. If e.g. I have a Person Class the Init procedure takes a parameter lNew. If lNew is True then I set defaults for all its properties (address, phone, etc.). This allows me to have procedures which may set e.g. the City field to some predefined value (as opposed to the ghost record which fills everything with blanks, etc). If lNew is False then I load all the properties from the current record including an nRec property which is the record # in the file or 0 if a new record is to be created. My Save routine uses this to determine if it should do a dbappend or goto that record, lock it, and update it. One other advantage of this approach is that the Person 'object' can be passed to other routines (e.g. a function to print an address label) as a single variable. Another is that I can have an inherited class override the Save method and do things like store the address in a totally different file. Garry Scott Krise wrote: > I am converting a text based data entry screen to a GUI screen, and I am > flip-flopping between setting the datalink for my entry field as a variable > (like I did in clipper), or to tie it directly to a database field using a > fieldblock. I am using the tdxget function from top-down to do my gets, and > I can see definite advantages to using fieldblocks, however I am running > into one specific problem doing it that way. If the I use the fieldblock > logic and start to ADD a record to the table, one of my first steps in the > ADD button logic is to do a dbappend()...which of course adds a blank record > to my table. If the user updates the information and clicks my SAVE > button....I'm good...If they decide not to update and hit my CANCEL button > to exit without saving...I'm good (I just delete the blank record they > created), however if something unusual happens and they do an END TASK of my > application from the task manager, then I am stuck with that blank record > being left out in my table. > > If I stick with using varibles as the datalink for my gets, I avoid this > problem, because I do the dbappend immediately before writing the variables > to the table, so this problem will never occur. > > I guess I'm wanting some opinions on how everyone deals with this in their > apps. > > Thanks, > > Scott > > > | |
Clayton Jones | Re: Using fieldblock as a datalink on Thu, 26 Oct 2006 18:30:42 -0400 Hello Scott, >If I stick with using varibles as the datalink for my gets, I avoid this >problem, because I do the dbappend immediately before writing the variables >to the table, so this problem will never occur. It really isn't all that different. The reason we used vars in Clipper was to temporarily store the data. In GUI we do exactly the same thing but the Get object is the storage mechanism. It does the job the vars used to do. The basic logic can be the same, as Jim said: wait until the save button before moving data fron the Gets to the table. As for passing data to sub routines, the same applies, we just do it a slightly different way: Clipper: myValidFunc(@cGetVar) Xpp: myValidFunc(oGet) More specifically in Top-Down, the bValid codeblock has the Get passed to it, represented by o here bValid := {|o| myValidFunc(o) } Same for altering the edited value in that sub routine Clipper: FUNCTION myValidFunc(cGetVar) xGetVar := 'abc' Xpp: FUNCTION myValidFunc(oGet) oGet:setData('abc') All the same logic applies, just the mechanism is a bit different. Using vars can be done, but it's just added and unnecessary work and in some cases can make it more difficult to take advantage of the powerful capabilities offered by OOP. IMO you'll be doing yourself a favor in the long run by biting the bullet and leave the vars behind. Regards, Clayton Clayton Jones www.cjcom.net Top-Down Library for Xbase++ X-DBU Database Utility X-MEMO Memo Field Replacement | |
Scott Krise | Re: Using fieldblock as a datalink on Fri, 27 Oct 2006 14:55:17 -0400 Hi Clayton, Yes...I agree. Since I originally posted this question, I have bitten the bullet and got rid of the variables. You are right that it really isn't that much different than using variables, and it does offer some some added benefits I didn't have before. The one thing I ran into that I did manage to work around (pretty ungracefully), but I'd like some suggestions on was what to do when you have some fields on the screen you want the user to be able to update...and others where you just want them to be able to view it. The way I have my system working now is that I set up my gets like this: oRMDesc := tdXget( 7.25,22.50,fieldblock('MAT_DESC'),oDa,50,oGetScreen,replicate("!",50)) oRMDesc:setData() aadd(aGets,oRMDesc) oRMDesc:aHelpmsg := {oStatbar,padc("Enter A Description Of The Raw Material", 235)} Then I use the aeval as follows when I'm ready to let them update: aeval(aGets,{|x,i| ; aGets[i]:editable := .T. ,; set to edit mode aGets[i]:configure() ,; reconfigure aGets[i]:setData() ,; refresh aGets[i]:cOriginal := aGets[i]:editBuffer() }) So my question is, how should I handle the database fields that I want them to see, but not be able to update? I like keeping all the fields on my screen within my aGets array so I can easily change the whole screen from editable to un-editable, etc...so what I'm doing is immediatly after I perform the aeval() to set everthing to editable, I go back through change the uneditable ones manually. Is there a better way to do this? Scott | |
Rodd Graham | Re: Using fieldblock as a datalink on Sat, 28 Oct 2006 00:27:04 +0000 Scott, FUNCTION ReadOnlyFieldWBlock( cFieldName, cnArea ) LOCAL cBlock := "{|x| ", bBlock, nArea := Select() DbSelectArea( cnArea ) IF FieldPos( cFieldName ) <> 0 IF Valtype( cnArea ) == "C" cBlock += cnArea+ '->' ELSE cBlock += "(" +LTrim(Str(cnArea))+ ")->" ENDIF cBlock += "(FIELD->"+cFieldName+") }" bBlock := &(cBlock) ENDIF DbSelectArea( nArea ) RETURN bBlock Note that I would always use a character alias and never a numeric work area number since it will properly work across thread boundaries in the event that the same table is open in different work areas in each thread. FYI: Original FieldWBlock() function from Alaska (source\SYS\Blocks.prg) **************************************************************************** * Data code block for fields in a given work area **************************************************************************** FUNCTION FieldWBlock( cFieldName, cnArea ) LOCAL cBlock := "{|x| ", bBlock, nArea := Select() DbSelectArea( cnArea ) IF FieldPos( cFieldName ) <> 0 IF Valtype( cnArea ) == "C" cBlock += cnArea+ '->' ELSE cBlock += "(" +LTrim(Str(cnArea))+ ")->" ENDIF cBlock += "(IIf(x==NIL,FIELD->"+cFieldName+","+ ; "FIELD->"+cFieldName+":=x)) }" bBlock := &(cBlock) ENDIF DbSelectArea( nArea ) RETURN bBlock Rodd > Hi Clayton, > > Yes...I agree. Since I originally posted this question, I have bitten > the bullet and got rid of the variables. You are right that it really > isn't that much different than using variables, and it does offer some > some added benefits I didn't have before. > > The one thing I ran into that I did manage to work around (pretty > ungracefully), but I'd like some suggestions on was what to do when > you have some fields on the screen you want the user to be able to > update...and others where you just want them to be able to view it. > The way I have my system working now is that I set up my gets like > this: > > oRMDesc := tdXget( > 7.25,22.50,fieldblock('MAT_DESC'),oDa,50,oGetScreen,replicate("!",50)) > oRMDesc:setData() > aadd(aGets,oRMDesc) > oRMDesc:aHelpmsg := {oStatbar,padc("Enter A Description Of The Raw > Material", 235)} > Then I use the aeval as follows when I'm ready to let them update: > > aeval(aGets,{|x,i| ; > aGets[i]:editable := .T. ,; set to edit mode > aGets[i]:configure() ,; reconfigure > aGets[i]:setData() ,; refresh > aGets[i]:cOriginal := aGets[i]:editBuffer() }) > So my question is, how should I handle the database fields that I want > them to see, but not be able to update? I like keeping all the fields > on my screen within my aGets array so I can easily change the whole > screen from editable to un-editable, etc...so what I'm doing is > immediatly after I perform the aeval() to set everthing to editable, I > go back through change the uneditable ones manually. Is there a better > way to do this? > > Scott > | |
Clayton Jones | Re: Using fieldblock as a datalink on Fri, 03 Nov 2006 09:52:48 -0500 Hello Scott, Sorry to take so long to reply, has been frantic around here lately. >oRMDesc := tdXget( >7.25,22.50,fieldblock('MAT_DESC'),oDa,50,oGetScreen,replicate("!",50)) >oRMDesc:setData() >aadd(aGets,oRMDesc) >oRMDesc:aHelpmsg := {oStatbar,padc("Enter A Description Of The Raw >Material", 235)} > >Then I use the aeval as follows when I'm ready to let them update: > >aeval(aGets,{|x,i| ; > aGets[i]:editable := .T. ,; set to edit mode > aGets[i]:configure() ,; reconfigure > aGets[i]:setData() ,; refresh > aGets[i]:cOriginal := aGets[i]:editBuffer() }) > >So my question is, how should I handle the database fields that I want them >to see, but not be able to update? I like keeping all the fields on my >screen within my aGets array so I can easily change the whole screen from >editable to un-editable, etc...so what I'm doing is immediatly after I >perform the aeval() to set everthing to editable, I go back through change >the uneditable ones manually. Is there a better way to do this? What you are doing here with Xgets is mimicing what the DE system already does - turn the Gets on and off. That is the fundamental difference between Xgets and DEgets. The way the DE system handles this is to use multiple arrays of Gets. aAllGets is used for updates. aEditGets is for those Gets you want to edit. You could do the same here. For example, if oGet3 is not to be edited it is added only to aAllGets. If oGet4 is to be edited it is added to both arrays. The aeval() above would operate only on aEditGets. The aeval used for updates would operate on aAllGets. The beauty of this approach is that these arrays can be passed around or assigned to different routines. If you look at the DEkeys() function you'll see how any number of Get arrays can be used. The one needed for the occasion is handed off to the "edit engine". I had a complex DE window once that had six different subsets of Gets for specialized editing. There were six different arrays besides aAllGets (aAllGets was used for navigational refreshing and for the AddRec routine). BTW, you are not increasing memory or resource use much by doing these multiple arrays. The arrays don't hold copies of the Get objects, but are merely pointers to the Gets. There is only one instance of each Get in memory. I hope this helps. Regards, Clayton Clayton Jones www.cjcom.net Top-Down Library for Xbase++ X-DBU Database Utility X-MEMO Memo Field Replacement | |
Scott Krise | Re: Using fieldblock as a datalink on Fri, 10 Nov 2006 09:24:03 -0500 Thanks Clayton. |