Griffon Update Model and View From Controller - swing

Hello I am new in Griffon Framework I want to add Login feature in my application. Follow are my model,view and controller:
SignInModel.groovy
#ArtifactProviderFor(GriffonModel)
#griffon.transform.Validateable
class SignInModel {
#Bindable String userName
#Bindable String password
static CONSTRAINTS = {
userName(blank: false,nullable: false)
password(blank: false, nullable: false)
}
}
SignInView.groovy
#ArtifactProviderFor(GriffonView)
class SignInView {
FactoryBuilderSupport builder
SignInModel model
SignInController controller
void initUI() {
builder.with {
application{
frame(title: 'Login', size: [330, 230],
show: true,resizable:false,locationRelativeTo: null,
defaultCloseOperation: EXIT_ON_CLOSE) {
panel(constraints: BorderLayout.CENTER,
border: compoundBorder([emptyBorder(10),titledBorder('Welcome To Tracker')])) {
tableLayout() {
tr {
td {
label(text: "Username")
}
td {
textField(id: "usernameTxt", columns: 15, text: bind(target: model, 'userName', mutual: true))
}
}
tr{
td{
label(text:"Password")
}
td{
passwordField(id:"passwordTxt",columns:15,text:bind(target:model,'password',mutual:true))
}
}
}
}
panel(constraints: BorderLayout.SOUTH) {
button text: 'Login', actionPerformed: {
model?.getErrors()?.clearAllErrors()
controller.signIn()
}
}
}
}
}
}
}
}
SignInController.groovy
#ArtifactProviderFor(GriffonController)
class SignInController {
SignInModel model
SignInView view
void signIn(){
try {
if (model?.validate()) {
println("No Error Found..")
} else {
println("Error Found..")
}
}catch (Exception ex){
println("Exception Generated:>>>>>>>>>>>>>>"+ex?.getMessage())
}
}
}
I want to update my SignIn View If username and password are empty with error message. I am able to get error message in my model but my view not update so Please help me.
#Note: I have added griffon validation plugin

You must process the errors property of the validateable (the model instance). This property contains a list of messages that can be used to display information back to the user, however you must choose which messages, as there may be many. Your current code is one step away from this as it has already triggered validation; now you just need to consume the messages and present them in the UI.

Related

How do I refresh HTML table after performing POST request in ngOnInit()?

Upon visiting the component invoices.ts , it looks in the background for some updates and applies them to the existing ones. Otherwise when the user has no existing invoices, it will perform a POST request to create them. However, when the user visits the component the POST and PUT operations are called in the ngOnInit() , i still see an empty table untill I refresh the page. How do i automatically refresh the HTML table to fill the newly made invoices without using `window.location.reload()' ?
invoice.component.ts
ngOnInit() {
this.auth.getProfile().subscribe((profile : any) => {
this.userName = profile.user.username;
this.email = profile.user.email;
}
this.getAndUpdateInvoices();
}
getAndUpdateInvoices() {
this.invoiceService.getInvoicesn().subscribe((data : any) => {
this.invoices= data.invoice;
this.createUpdate();
})
createUpdate() {
this.createInvoice({
client: data.Client,
***etc
})
}
createInvoice(invoice) {
this.invoiceService.newInvoice(invoice).subscribe((data: any) => {
if (!data.success) {
console.log(data.message);
} else {
console.log(data.message);
}
});
}
this.invoiceService.updateInvoice(this.invoice).subscribe((data: any) => {
if (!data.success) {
console.log(data.message);
} else {
console.log(data.message);
}
});
}
In my invoice.component.html:
<tr *ngFor="let invoice of invoices" >
<td> {{invoice.hours}} </td>
Please let me know if you need more info
just call the method which is being used for fetching all the data from your service class here :
createInvoice(invoice) {
this.invoiceService.newInvoice(invoice).subscribe((data: any) => {
if (!data.success) {
console.log(data.message);
} else {
console.log(data.message);
-----HERE----
}
});
}

Unable to run multiple GET methods in single controller

I have created a WEB API in visual studio 2015 using MySQL DB. I have three GET methods. One is which gives all the data, second one is which gives the result based on ID and 3rd one is which should gives result on basis of a serial number. First two methods are working perfect but the last one is not. I have also added multiple Routes in the solution. Below is my code
WebApiConfig
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "GetByMsn",
routeTemplate: "api/{controller}/{action}/{msn}",
defaults: null,
constraints: new { msn = #"^[a-z]+$" }
Controller
public HttpResponseMessage Get()
{
try
{
return Request.CreateResponse(HttpStatusCode.Found, mEntities.meters_info_dev.ToList());
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
}
// GET by ID
public HttpResponseMessage GetByID(int id)
{
try
{
return Request.CreateResponse(HttpStatusCode.Found, mEntities.meters_info_dev.SingleOrDefault(m => m.id == id));
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
}
// GET by serial number
public HttpResponseMessage GetByMsn(string msn)
{
try
{
return Request.CreateResponse(HttpStatusCode.Found, mEntities.meters_info_dev.SingleOrDefault(m=> m.meter_msn == msn));
}
catch
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Data found");
}
}
GetByMsn is the one which is not working. I have tried to change the routes but still the result is same. The solution 1 and solution 2 given are not working for me.
Any help would be highly appreciated.
config.Routes.MapHttpRoute(
name: "GetByMsn",
routeTemplate: "api/{controller}/{action}/{msn}",
defaults: null,
constraints: new { msn = #"^[a-z]+$" }
In above the constraints were alphabetic, I just change it to #"^[0-9]+$" and it starts working for me.

How to POST an object with its childrens ? grails 3 RESTful - security - POST save new objects

I am trying to do a simple POST to save a new object
class diagram
I want to POST a Question with the following attributes:
String name
static hasOne = [questionType: QuestionType]
Each Question has one abstract QuestionType extended by one of this objects:
Mcq (Multiple Choice Question)
SourceCode
Matching
...
For my Mcq, I have the following attributes:
static belongsTo = [questionType: QuestionType]
static hasMany = [propositions: Proposition]
static constraints = {
}
static mapping = {
propositions cascade: 'all-delete-orphan'
}
So my Mcq owns 0 to many Proposition
A Proposition is made of:
String body
Boolean isCorrect
String reason
I am using Postman to check my API. I don't have any UI for now.
My Question, Qcm and Proposition objects have a controller and a service to manage them.
My QuestionService:
class QuestionService {
def save(Question question) {
if (question == null) {
transactionStatus.setRollbackOnly()
render status: NOT_FOUND
return
}
if (question.hasErrors()) {
transactionStatus.setRollbackOnly()
respond question.errors, view:'create'
return
}
question.save flush:true
}
def update(Question question) {
if (question == null) {
transactionStatus.setRollbackOnly()
render status: NOT_FOUND
return
}
if (question.hasErrors()) {
transactionStatus.setRollbackOnly()
respond question.errors, view:'edit'
return
}
question.save flush:true
}
def delete(Question question) {
if (question == null) {
transactionStatus.setRollbackOnly()
render status: NOT_FOUND
return
}
question.delete flush: true
}
}
My QuestionController:
#Secured('ROLE_ADMIN')
#Transactional(readOnly = true)
class QuestionController {
//spring bean injected for the Controller to access the Service
def questionService
static responseFormats = ['json', 'xml']
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
//views
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Question.list(params), model:[questionCount: Question.count()]
}
def show(Question question) {
respond question
}
//actions
def save(Question question){
try { questionService.save question }
catch (e){ respond status: PRECONDITION_FAILED }
respond question, [status: CREATED, view:"show"]
}
def update(Question question) {
try { questionService.update question }
catch (e) { respond status: PRECONDITION_FAILED }
respond question, [status: OK, view:"show"]
}
def delete(Question question) {
try { questionService.delete question }
catch (e){ respond status: PRECONDITION_FAILED }
respond status: OK, view:"index"
}
}
I can get each Proposition, Mcq and Question with my index and show actions.
I don't allow my users to POST a new Proposition / Mcq. If they want to do it, they have to UPDATE the full Question itself. So only my Question can be modified (and modify others), others or in read-only.
My problem is that I can NOT POST this:
{
"name": "name1",
"questionType": {
"propositions": [
{
"body": "body proposition 1",
"isCorrect": true,
"reason": "reason proposition 1"
},
{
"body": "body proposition 2",
"isCorrect": false,
"reason": "reason proposition 2"
}
]
}
}
It always returns me a
[
null
]
But this works:
{
"name": "name1",
"questionType": {
"id": 1
}
}
So, in here, I can refer to a QuestionType already in my database (from my bootstrap) but I don't see how to create in cascade all of my Question, QuestionType, Qcm and Proposition.

How to add image attributes in Quill editor? I want to add 'alt' and 'title' attribute

When I upload an image, only its 'src' is saved. I want to add alternate text and title for SEO purpose. I tried searching for a module in the Quill documentation, but could not find any.
Maybe not the direct answer but related.
Here is the solutions to keep attributes for image when initializing from full text html.
Solution1:
class ImageBlot extends Image {
static create(value) {
if (typeof value == 'string') {
return super.create(value);
} else {
return value;
}
}
static value(domNode) {
return domNode;
}
}
Quill.register(ImageBlot);
Solution2:
class ImageBlot extends Image {
static get ATTRIBUTES() {
return [ 'alt', 'height', 'width', 'class', 'data-original', 'data-width', 'data-height', 'style-data' ]
}
static formats(domNode) {
return this.ATTRIBUTES.reduce(function(formats, attribute) {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute);
}
return formats;
}, {});
}
format(name, value) {
if (this.constructor.ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value);
} else {
this.domNode.removeAttribute(name);
}
} else {
super.format(name, value);
}
}
}
Quill.register(ImageBlot);
You can specify the whitelist for attributes with solution2.

Grails use SQLQuery result as transient value in domain class rendering

Let's say i have the following domain classes:
The first domain class Tag.groovy allows me to build a dynamic category structure with different layers (layer1, layer2 and layer3). Each activity from Activity.groovy belongs to a certain category and is connected to its category via ActivityTag.groovy. So far so good. :)
Tag.groovy
class Tag {
String name
String layer
Tag parent
static transients = ['activityCount', 'children']
int activityCount
static constraints = {
name nullable: false, unique: true
layer nullable: false, inList:['generic','layer1','layer2','layer3']
parent nullable: true
}
Set<Tag> getChildren() {
return Tag.findAllByParent(this) as Set
}
Set<Activity> getActivities() {
return ActivityTag.findAllByTag(this)*.activity
}
Set<Activity> getActivities(VirtualCity virtualCity) {
def activitiesWithTag = ActivityTag.findAllByTag(this)*.activity
return activitiesWithTag.findAll({it.virtualCity==virtualCity})
}
def getActivityCount(){
if (this.layer == "layer1") {
return this.children*.children*.activityCount.sum().sum()
} else if (this.layer == "layer2") {
return this.children*.activityCount.sum()
} else {
return this.getActivities().size()
}
}
def getActivityCount(VirtualCity virtualCity){
if (this.layer == "layer1") {
return this.children*.children*.activityCount.sum().sum()
} else if (this.layer == "layer2") {
return this.children*.activityCount.sum()
} else {
return this.getActivities(virtualCity).size()
}
}
}
Activity.groovy
class ActivityTag {console
Activity activity
Tag tag
static mapping = {
id composite: ['activity', 'tag']
version false
}
}
ActivityTag.groovy
class Activity {
VirtualCity virtualCity
String name
}
Now I would like to render my categories as JSON in a tree view. Can you tell me how I can achieve this?
I tried render(template: "tree", collection: Tag.findAllByLayer("layer1"), var: 'tag')
with this template _tree.gson:
model {
Tag tag
}
json {
id tag.id
name tag.name
activityCount tag?.activityCount ?: null
children g.render(template: 'tree', collection: tag?.children, var: 'tag') ?: null
}
But this method fails with java.lang.reflect.InvocationTargetException: null