Troubleshooting Moodle App Plugins Development
Invalid response received
You might receive this error when using the core-site-plugins-call-ws
directive or similar. By default, the app expects all Web Service calls to return an object, if your Web Service returns another type (string, boolean, etc.) then you need to specify it using the preSets
attribute of the directive. For example, if your WS returns a boolean value, then you should specify it like this:
[preSets]="{typeExpected: 'boolean'}"
In a similar way, if your Web Service returns null
you need to tell the app not to expect any result using preSets
:
[preSets]="{responseExpected: false}"
Values of ion-radio
, ion-checkbox
or ion-select
aren't sent to my WS
Some directives allow you to specify a form id or name to send the data from the form to a certain WS. These directives look for HTML inputs to retrieve the data to send. However, ion-radio
, ion-checkbox
and ion-select
don't use HTML inputs, they simulate them, so the directive isn't going to find their data and so it won't be sent to the Web Service.
There are 2 workarounds to fix this problem.
Sending the data manually
The first solution is to send the missing params manually using the params
property. We will use ngModel
to store the input value in a variable, and this variable will be passed to the parameters. Please notice that ngModel
requires the element to have a name, so if you add ngModel
to a certain element you need to add a name too.
For example, if you have a template like this:
<ion-list radio-group name="responses">
<ion-item>
<ion-label>First value</ion-label>
<ion-radio value="1"></ion-radio>
</ion-item>
</ion-list>
<ion-button expand="block" type="submit" core-site-plugins-call-ws name="myws" [params]="{id: <% id %>}" form="myform">
{{ 'plugin.mycomponent.save' | translate }}
</ion-button>
Then you should modify it like this:
<ion-list radio-group [(ngModel)]="responses">
<ion-item>
<ion-label>First value</ion-label>
<ion-radio value="1"></ion-radio>
</ion-item>
</ion-list>
<ion-button expand="block" type="submit" core-site-plugins-call-ws name="myws" [params]="{id: <% id %>, responses: responses}" form="myform">
{{ 'plugin.mycomponent.save' | translate }}
</ion-button>
Basically, you need to add ngModel
to the affected element (in this case, the radio-group
). You can put whatever name you want as the value, we used "responses". With this, every time the user selects a radio button the value will be stored in a variable called "responses". Then, in the button we are passing this variable to the parameters of the Web Service.
Please notice that the form
attribute has priority over params
, so if you have an input with name="responses"
it will override what you're manually passing to params
.
Using a hidden input
Since the directive is looking for HTML inputs, you need to add one with the value to send to the server. You can use ngModel
to synchronise your radio/checkbox/select with the new hidden input. Please notice that ngModel
requires the element to have a name, so if you add ngModel
to a certain element you need to add a name too.
For example, if you have a radio button like this:
<div radio-group name="responses">
<ion-item>
<ion-label>First value</ion-label>
<ion-radio value="1"></ion-radio>
</ion-item>
</div>
Then you should modify it like this:
<div radio-group name="responses" [(ngModel)]="responses">
<ion-item>
<ion-label>First value</ion-label>
<ion-radio value="1"></ion-radio>
</ion-item>
<ion-input type="hidden" [ngModel]="responses" name="responses"></ion-input>
</div>
In the example above, we're using a variable called "responses" to synchronise the data between the radio-group
and the hidden input. You can use whatever name you want.
I can't return an object or array in otherdata
If you try to return an object or an array in any field inside otherdata
, the Web Service call will fail with the following error:
Scalar type expected, array or object received
Each field in otherdata
must be a string, number or boolean; it cannot be an object or array. To make it work, you need to encode your object or array into a JSON string:
'otherdata' => ['data' => json_encode($data)],
The app will automatically parse this JSON and convert it back into an array or object.