Sunday, August 31, 2014

ng-select ng-options

I can see the potential of the AngularJS modifications to the SELECT element. I see the advantages of having an object reference when a user has made a choice. It would simplify further processing choices. It's all great, well until you hit the documentation.

  • for array data sources:
    • label for value in array
    • select as label for value in array
    • label group by group for value in array
    • select as label group by group for value in array track bytrackexpr
  • for object data sources:
    • label for (key , value) in object
    • select as label for (key , value) in object
    • label group by group for (key, value) in object
    • select as label group by group for (key, value) in object
Where:
  • array / object: an expression which evaluates to an array / object to iterate over.
  • value: local variable which will refer to each item in the array or each property value of object during iteration.
  • key: local variable which will refer to a property name in object during iteration.
  • label: The result of this expression will be the label for  element. Theexpression will most likely refer to the value variable (e.g. value.propertyName).
  • select: The result of this expression will be bound to the model of the parent element. If not specified, select expression will default to value.
  • group: The result of this expression will be used to group options using the DOM element.
  • trackexpr: Used when working with an array of objects. The result of this expression will be used to identify the objects in the array. The trackexpr will most likely refer to the value variable (e.g. value.propertyName).
Hunh? What if you simply want a value for each option, you know, like you used to get back in the old days? Here is our options

$scope.unitOptions =[{VALUE:"CRB11",LABEL:"20FT CONTAINER"},{VALUE:"CRB12",LABEL:"40FT CONTAINER"},{VALUE:"CRB3",LABEL:"CARTONS"},{VALUE:"CRB6",LABEL:"ENVELOPES"},{VALUE:"FRT25",LABEL:"ITEMS"},{VALUE:"CRBx2",LABEL:"ITEMS IN THE LOT"},{VALUE:"CRBx1",LABEL:"LITRES"},{VALUE:"CRB5",LABEL:"PALLETS"},{VALUE:"CRB14",LABEL:"PALLETS OR SKIDS"},{VALUE:"CRB4",LABEL:"SKIDS"},{VALUE:"FRFCB16",LABEL:"SPA"}];
So item_units will receive the opt.VALUE rather than a reference to an object. From the above "opt.VALUE as opt.LABEL for opt in unitOptions" matches the form "select as label for value in array" from the documentation. I read that as ;
opt.VALUE is the id for the displayed opt.LABEL for each of the opt objects in unitOptions 
Not complaining, Angular is a great way of organizing the frontend. I can see why they wrote it the way they did, but it doesn't bring us any closer to literate programming.

Tuesday, March 4, 2014

ng-click on an anchor tag = pain

What do you do when things goes snap in AngularJS?
Here is the controller code:

var Controllers = angular.module('Controllers', ['ngRoute']);
Controllers.config(
function ($routeProvider){
$routeProvider
.when('/', {
controller: 'PalletListCtrl',
templateUrl: '/closeAndUplift_palletList.html'
})
.when('/edit/:id', {
controller: 'PalletEditCtrl',
templateUrl: '/closeAndUplift_palletEdit.html'
})
.when('/add', {
controller: 'PalletEditCtrl',
templateUrl: '/closeAndUplift_palletEdit.html'
})
.otherwise({
redirectTo: '/'
});
}
);

Controllers.controller('PalletListCtrl',function ($scope, $location, $route){
   console.log($route);
$scope.addPallet = function(){
$location.path('/add');
};
});
Controllers.controller('PalletEditCtrl', function ($scope, $location, $routeParams, $route){
    console.log($route);
});

And the HTML:



Well it doesn't look that difficult to me.
closeAndUplift_palletList.html loads and addPallet fires. This makes closeAndUplift_palletEdit.html download from the server, but nothing renders on the screen. At this point what do you do? How do you debug it?
Well, if you do go the debug route you step through $location.path('/add'); and end up in the digest portion looking at a comment;
//Insanity Warning: scope depth-first traversal
// yes, this code is a bit crazy, but it works and we have tests to prove it!

At this point you think to yourself that it might be a good day to go fishing.

The problem turned out to be the click event.
The addPallet was called like this...
<a class="round button" href="#" ng-click="addPallet()">Add</a>
Changing to 
<button class="round button" href="#" ng-click="addPallet()">Add</button>
resolved the problem.

So the problem wasn't with Angular but rather an inability to debug the way a browser loads/reloads pages. The problem is you can't return false from the ng-click to block the default anchor action.

Tuesday, February 25, 2014

A nail in the technology coffin?

Something to consider:
In the UK, early evidence of large scale nail making comes from Roman times 2000 years ago.

To think the humble nail held its own for so long. However, had the blacksmiths of the day had a better marketing team perhaps we could have done away with the trusty iron technology of the day and perhaps moved on to I don't know ... wooden ones? They wouldn't have done the job as well, but they would have been cheaper to make. 

I think there would have been some backlash (or some lashed backs) when the Roman forts started falling down.

But now we have moved on from those historic days. All the marketing gurus have to say is "End of life..", and it is so, and everyone starts rebuilding forts with cheaper nails..

If I am being a bit vague, a case in point is the poor guy who rewrote his Foxpro application in Silverlight. That application would have continued to run for years under VFP. 

There are compelling reasons to move with new technology, but, because you were told to, is not one of them.

Now the screw, that was an innovation! But it didn't appear until the 15th century. So if my counting serves me correctly the nail held its domination for 6-700 years

So remember that the next time you get nailed by a technology company, wait for an innovative technology to appear and then say screw you.

Simple intro to using Python with IIS

Create an application
Add a script map
Request Path: *.py
Executable: C:\Python25\Python.exe %s %s
Name: Python

Add a file to the directory call it test.py
print
print 'Status: 200 OK'
print 'Content-type: text/html'
print
print ''
print ''
print '

This is a header

'
print '
' #this is a comment
print 'See this is just like most other HTML'
print '
'
print ''

Navigate to http://localhost/myWeb/test.py

Query strings and other HTTP parameters can be accessed through:
method = os.environ["REQUEST_METHOD"]
if method == "GET":
query = cgi.FieldStorage()
coName = query.getvalue("co")

AngularJS and IE 8

I need to support IE within desktop applications and MS sent XML data islands to the grave. XML data islands were an undervalued technology, particularly for databinding. Data islands are supported in later versions of IE through a backwards compatibility mode but that doesn't help with Chrome.

So naturally the gap gets filled and while there are many contenders it looks like AngularJS is the overall winner because you get so much out of the box. Why MS couldn't have done something similar is beyond me.
So AngularJS can run in IE and Chrome, but there's a catch. The following runs in Chrome but not in IE.













After lots of searching I found that you need this:

at the top of the HTML. It occurs when you are using AngularJS with Strict Contextual Escaping (SCE) mode enabled (the default) on IE8 or lower in quirks mode.

Thursday, May 27, 2010

Python and COM

Py2Exe can create OLE COM servers. In particular the sample that ships with py2exe creates the Python interpreter. That means win32 programs can execute Python scripts without having to deploy the Python Win32 extensions. That makes distributing apps that use Python scripting easier.
I am going to do this on Windows and access the Python objects through COM from Visual Foxpro. Just because M$ decided not to continue with the Fox doesn't stop it from being a great environment to play around in.

Executing:
C:\Python25\Lib\site-packages\py2exe\samples\pywin32\com_server>python setup.py py2exe
Creates a dist directory
C:\Python25\Lib\site-packages\py2exe\samples\pywin32\com_server\dist
Within the dist directory
regsvr32 interp.dll

Now we need a program (People.py) that gives us access to Python objects without having to expose each Python class as a COM server. Unfortunately in the following spaces are collapsed, and when reading Python code that is not a good thing!

import win32com.client

class Person(object):
_public_methods_ = ['getName']
_public_attrs_ = ['firstName']
def __init__(self, name):
self.firstName = name

def getName(self):
return self.firstName

class Student(Person):
def __init__(self, name):
super(Student, self).__init__(name)
# append the public methods and properties,
# otherwise the inherited Person._public_...
# would not be available to the COM client
Person._public_methods_.append('setExamResults')
Person._public_attrs_.append('examResults')

def setExamResults(self, exam):
# Exam is passed in from a COM client
self.examResults = win32com.client.Dispatch(exam)

In Visual Foxpro "*" is a comment, and "?" means print. Everything else should be pretty obvious.
From VFP:
oP = CreateObject("Python.Interpreter")
oP.Exec("import sys")
oP.Exec("from win32com.server.util import wrap")
? "The COM object is being hosted in " + oP.Eval("sys.executable")
? "Path is:" + oP.Eval("str(sys.path)")
oP.Exec('sys.path.append("c:\\temp")')
oP.Exec( "import People")
oP.Exec( "student = People.Student('Peter')")
* Get the object from Python into VFP by wrapping it
student = oP.eval("wrap( student )")
* Now call a function on that object
? student.getName()
* Displays "Peter"

* Create a VFP object to pass into Python
oExam = CREATEOBJECT("empty")
ADDPROPERTY(oEmpty,"English",86)

* Pass it in
student.setExamResults(oEmpty)

* Test that it has attached.
? student.examResults.English

* Displays 86

So what was the benefit of all that? Hmmm, imagine if we could call SQLalchemy objects from anywhere!! Or what if you have a legacy (only because M$ decreed it that way) app and wanted to continue to expand its functionality in an open source language.

Tuesday, August 4, 2009

TiddlyWikis and a web server

There are a number of options around for making tiddlywikis editable across the web. However, what if all you want to do is to be able to edit locally and have it viewed publicly? If you want to develop on a laptop and make notes along the way, then you would need to edit the file and copy it to the web server across the network. Remembering to do that is just too much work.
Even if you were happy to edit the file directly on the web server across the network, there is a problem in that the tiddlywiki will fail on save if you are accessing it from a network drive.

I tried synchronizing folders with the web server but ran into the problem of saving the wiki, it must have something to do with the naming of the synchronization directory.

But there is a really simple answer, and it integrates into something you are probably already doing. Robocopy! I already have scheduled robocopy scripts that are backing up files to an external drive on the network. Well then, just increase the script to take your wikis to your web server ... done!

The great thing about this approach is that your blog can link to your wikis. Wikis can be more domain oriented, and within the wiki you have your tags for crosslinking.