I've been fiddling with this for a while and stumble upon an answer, so I thought I'd post it in hopes that it may save someone else some time.
On CF11, my binding parameter looks like this:
<cfset args.bind = 'cfc:data.RecordSelect({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},"#DataSelect.tableName#","#DataSelect.dsn#",{gridForm:searchColumn},gridForm:searchBox},"#DataSelect.PKName#","#variables.gridColumnsForGrid#")'>
With CF11, this ran just fine, and it works by and large on CF2018, too. The grid sorts, updates, add new records, and delete records. But I also have a dropdown for a filter, and when I try to filter, I get this error:
Element not found: "gridColumn|gridHeading|gridDataType|gridMask|tableName|PKName|searchable|dsn" [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]
The element is the list of columns I'm passing to the CFC.
Here's the solution:
<cfset args.bind = 'cfc:data.RecordSelect({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{gridForm:tableName},{gridForm:dsn},{gridForm:searchColumn},{gridForm:searchBox},{gridForm:PKName},{gridForm:gridColumnsForGrid})'>
<cfinput type="hidden" name="tableName" id="tableName" value="#DataSelect.tableName#" />
<cfinput type="hidden" name="dsn" id="dsn" value="#DataSelect.dsn#" />
<cfinput type="hidden" name="PKName" id="PKName" value="#DataSelect.PKName#" />
<cfinput type="hidden" name="gridColumnsForGrid" id="gridColumnsForGrid" value="#variables.gridColumnsForGrid#" />
So what this means, from my experience, is that you can no longer pass non-bracketed elements via binding. Maybe this was how I was always supposed to do it, as either way works in CF11.
Of course I know we're not supposed to be using CFGRID anymore since it'll lead to disappointment and ruin...but this is old code and I can't take the time to convert this over to DataTables just yet. :)
Related
I'm using currently Primefaces 6.1 and i got following Datatable:
<prime:column headerText="Status" filterBy="#{zoneAccSum.statusImage(zoneAccess.request.id)}"
filterMatchMode="equals">
<f:facet name="filter">
<prime:selectOneButton styleClass="theme-running" onchange="PF('data').filter()" >
<f:selectItems value="#{zoneAccSum.statusButtons}" />
</prime:selectOneButton>
</f:facet>
<prime:graphicImage value="#{zoneAccSum.statusImage(zoneAccess.request.id)}" />
</prime:column>
<prime:column headerText="Details" style="text-align:center; width:150px;">
<prime:commandButton value="Details" id="ajax" actionListener="#{zoneAccSum.redirect(zoneAccess.id)}" oncomplete="PF('requestModal').show()" update="SummaryFormZone:zone" />
</prime:column>
So the filtering just works fine, it shows me the right result. But if i use the commandButton after filtering, the passed value I get is always 0. To clarify i got my Bean already ViewScoped and Serialized and my Button sets an Value in Bean where my Modal Panel can request it's data from.
Does anyone know, how i can fix getting 0 all the time or how i can build a workaround?
I tried couple of things today and figured it finally out myself. For other people who might encounter this i will post my solution here:
Primefaces somehow needs an extra List in the Managed Bean for Filter purposes. So at the first datatable tag, you need to add following:
<prime:dataTable var="zoneAccess" value="#{zoneAccSum.data}" widgetVar="data" rows="10" paginator="true" filteredValue="#{zoneAccSum.filteredData}">
The filteredValue tag
In your Managed Bean just add a new list with the with the given name, in this case filteredData, and Primefaces now no longer will pass null values
I have a screen built with a several stacks of ng-includes. The last one, in special, I build the screen based on user configuration.
Sometimes, I have to show a Form in one of this included templates. And when my user click on save button, I have to validate if all fields in the form are valid.
In the meantime, when a try to access form object, to check for $valid, my form is undefined.
After a day fighting against it, I've discovered that ng-include process is not accepting my form object to be created.
I've created this plunker to see if it's really happening on a simple project, making a working form and not working one:
http://plnkr.co/edit/4oMZYLgaYHJPoSZdSctI?p=preview
Basically, created a form, like this, with demanded angular attributes:
<form name="sampleForm">
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
<br/>
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
</form>
And trying to access form object like this:
$scope.sampleForm.aws.$valid
And the result is:
$scope.sampleForm === undefined
Someone know how to solve this problem?
Since ng-include creates a new scope, $scope.sampleForm will be undefined from within the included page.
The solution should be getting the ng-controller="formController" declaration inside of the included HTML page itself, which I think is also a better design, since I can't see a scenario where it's not "controlling" the form.
The other non-included form obviously works as you might expect.
Plunker
This was taken from a e-mail thread between me and the author. I've moved it from e-mail to SO hoping that it may benefit others. ElasticUI can be found here
My Original Question(s)
I see that search is eui-enabled by querystring.length. We would like to the search and sorting triggered by buttons, rather than the
watch functionality.
It's a bit confusing when the search returns no results. Instead of a no results found message it simply returns the deafualt (all)
results. Is it possible to make the results empty by default, rather
than return all?
Author's Answer
1+2 - this is both possible. In AngularJS, keep in mind what "model"
variable you use and connect to your UI / Directives, something along
the following lines would make sense
<div eui-query="ejs.MatchQuery('textField', querystring)" eui-enabled="querystring.length"> <input type="text" ng-model="querystring_live" />
<input type="button" ng-click="querystring=querystring_live" /> </div>
<div ng-if="!querystring.length"> No query specified </div>
Notice what happens on a click. You could also wrap an ng-if clause
around you're results to only display results when a query has been
specified.
When I include this snippet, the ng-if condition doesn't take (the "No query specified" stays at all times) and after submitting the search, results are blank, even if it's query I'm sure should return results.
Being new to angular, an obvious mistake may go over my head. Is there anything obvious that is missing?
Edit
Found the issue: Forgot to fill in the field with which to run the query against: eui-query="ejs.MatchQuery('post_title', querystring)" ('post_title' being the ES field)
Although it seems like you may have found the answer I think there's still a bug in the "author answer" (me) you posted above. Seems like I fell for the dot-problem in Angular. This should work better:
<div ng-init="qs_model={live:'', after_click:''}">
Debug: {{qs_model | json}}
<h3>Search</h3>
<div eui-query="ejs.MatchQuery('tweet.text', qs_model.after_click)" eui-enabled="qs_model.after_click.length">
<input type="text" ng-model="qs_model.live" />
<input type="button" ng-click="qs_model.after_click=qs_model.live" />
</div>
<div ng-if="!qs_model.after_click.length">No query specified </div>
</div>
It's cleaner to define qs_model in a controller as opposed to ng-init I demoed above.
Also note that even if eui-query is disabled (no querystring specified), ElasticUI will at this moment still do a MatchAll query behind the scenes (you can choose to hide the results using ng-if).
I am sorry for asking such a noob question. But I saw a video very long time ago and I think it was a framework based on jquery, where if a user makes some CRUD changes to an object, the object's properties are auto updated not only for 1 user, but on all the other users browser. I am trying to find it but I am all lost! I would really really appreciate if you could help me out. Thank you!
Lets say you have a html form that looks like this
<form>
<input type="text" name="firstName" value="Jackson" />
<input type="text" name="lastName" value="Rivera" />
<textarea name="lifestory">
When i was 2yo, spot died...
</textarea>
</form>
simply add an OnChange event on every element you want to dynamicly change:
<form>
<input .. .. onchange="shareValueWithOthers(this.name, this.value)"/>
<input .. .. onchange="shareValueWithOthers(this.name, this.value)"/>
<textarea onchange="shareValueWithOthers(this.name, this.innerHTML)">
When i was 2yo, spot died...
</textarea>
</form>
Notice that a change of the elements value (or in the case of the textarea - it's contents) causes the function shareValueWithOthers(this.name, this.value) starts to run. this.name is the variable for the name, this.value is the variable for the value, this.innerHTML is the variable for the contents.
Now you have to write a Javascript function so you can send the changes to the server. Look into AJAX. Make a function that sends a POST request to your PHP script.
Your PHP script should save all the values either in a database, or in JSON-format in a file on the server. JSON is the easiest. Look into JSON PHP PARSER.
Last but not least. If you do the right thing, and make sure that every new value that a user enters gets updated in your json file by your PHP script. You can make the last step. which is to make a javascript function that retrieves the JSON file. JSON stand for JavaScript Object Notation, so your javascript can use this right away.
What you will do next, is to change all the values in your DOM that look different from the values in your retrieved JSON object.
two type of protocol, Websocket or WebRTC.
socket.io is Websocket very popular and easy.
gevent-socketio for python
Plenty base on node.js. sailsjs, deployd, meteor
I've been struggling all afternoon with this problem and couldn't find any viable solution online, so here we go. I'll try my best to be thorough regarding my problem as I already boiled down its main elements (in other words, some of my code here is gonna be a simplified example and I'm gonna tell bits of the story here and there for better understanding). First off, I use EXT.NET MVC model and I use markup to a great extent. So, here's my store (actual code):
<ext:Store ID="storeActivityProjectHistory" runat="server" UseIdConfirmation="true">
<Reader>
<ext:JsonReader IDProperty="idProject">
<Fields>
<ext:RecordField Name="idActivity" Type="Int" />
<ext:RecordField Name="idProject" Type="Int" />
<ext:RecordField Name="nmProject" Type="String" />
<ext:RecordField Name="csStatus" Type="String" />
<ext:RecordField Name="dsDetails" Type="String" />
<ext:RecordField Name="dtDate" Type="Auto" DateFormat="MM/yyyy" />
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
A bit of insight: an Activity might contain several Projects. Usually one would expect the other way around, but it is not. And this is the grid I linked to this store (I removed several tags from this one, for simplicity's sake):
<ext:GridPanel ID="grdActivityProjectHistory" runat="server" StripeRows="true" Title='<%# Html.GetText("History") %>' Width="621" AutoHeight="true"
StoreID="storeActivityProjectHistory">
<ColumnModel>
<Columns>
<ext:Column ColumnID="idActivity" DataIndex="idActivity" Hidden="true" />
<ext:Column ColumnID="idProject" DataIndex="idProject" Hidden="true" />
<ext:Column ColumnID="nmProject" Header="Project" DataIndex="nmProject" Width="250" />
<ext:Column ColumnID="dsDetails" DataIndex="dsDetails" Hidden="true" />
<ext:Column ColumnID="csStatus" Header="Status" DataIndex="csStatus" Width="75" />
<ext:DateColumn ColumnID="dtDate" Header="Date" DataIndex="dtDate" Width="75" Format="MM/yyyy" />
</Columns>
</ColumnModel>
</ext:GridPanel>
Now, some explanation is due: whenever an Activity is created, the user might link one or several Projects to it. Also, he can change this LINK's status to flag whether the project is active or inactive within the Activity. Changes in this link must be stored in a history, which is what the grid and store above provide support to.
Whenever this link is created, it must be active and have a default detail ("Record created"). Since it is a default behavior and we use a lot of stored procedures to deal with the DB, I figured that whenever a new link is created, I could just insert these values straight into the database from the SP itself. In other words, whenever a link is created, there will already be one record in history.
This is how I load said record into the store upon loading the activity and that is, what I suppose, part 1 of what messes things up (don't worry about the projectId variable):
var fillActivityProjectStore = function(projectId) {
var activityProjectHistoryList;
currentProjectHistoryList = new Array();
if (loadedActivity.activityProjectHistoryList!= null) {
activityProjectHistoryList = loadedActivity.activityProjectHistoryList.Original;
activityProjectHistoryList.forEach(function(activityProjectHistory) {
if (activityProjectHistory.cdProject == projectId)
currentProjectHistoryList.push(activityProjectHistory);
});
storeActivityProjectHistory.loadData(currentProjectHistoryList);
}
}
The explanation to this apparent mess: loadedActivity.activityProjectHistoryList.Original holds all history information of all projects linked to the current loaded activity and here I select the information relative only to one of those projects and load into the store.
And, for the gran finale, whenever I try to change the status of this link (which should add a second line in the grid, under the current line already loaded), is when I recieve the dreadful "Uncaught TypeError: Cannot read property 'data' of undefined"
This is how I try to add a new line:
var addNewHistoryRecord= function() {
if (selectedLineIndex> -1) {
var record= storeProjects.getAt(selectedLineIndex).data;
var recordHistory= {
idActivity: 0, //Server-side handles it
idProject: record.idProject,
nmProject: record.nmProject,
dsDetails: dsDetailsField.getValue(),
csStatus: csStatusField.getValue(),
dtDate: dtDateField.getValue()
}
storeActivityProjectHistory.addRecord(recordHistory); // <--RIGHT HERE!
}
}
Well, I'm sorry about the overly long post and the stupid variable names, I had to hastly translate them to english because we use our native language in code (which sucks). I'm pretty sure that the relationship between the storeActivityProjectHistory.loadData and storeActivityProjectHistory.addRecord methods are my problem, but I just don't know what to do about it. Thanks in advance and if more code is needed, I'll post more code (for instance, one might notice some global variables and a "storeProject" in the last javascript method that I hadn't mentioned before, but I don't think it is actually relevant). Hope you guys can help!
Edit: As instructed, I have changed store.addRecord to store.add and now it returns the following error in the same point:
Uncaught TypeError: Object #Object has no method 'join'
Any ideas?
Ok, I found the answer. Thanks is due to Reimius for making me stop being lazy and actually pay attention to the documentation. A generic object just won't work with store.add(), a subclass instance of Ext.data.Record is needed.
In order to do so, here's the neat template I have followed and solved my problems in less than 10 minutes: http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.Record-static-method-create
And even though the documentation itself says that store.add accepts a Ext.data.Record[], I didn't use it, after I created the object (that is, recordHistory) in the proper way, a mere
storeActivityProjectHistory.add(recordHistory) did the trick.