createRecord is creating a record with null - javascript

I have hasMany property.
Here is my model
status: DS.attr(),
OnInsert: DS.attr('boolean',{defaultValue: true}),
rOnUpdate: DS.attr('boolean',{defaultValue: false}),
filterQuery:DS.attr({defaultValue: {"condition": "AND", "subRules": [], "subGroups" : []}}),
ruleCase:DS.hasMany('rule',{async:true}),
In my hbs i have created button with some action on it:
Here is my hbs code:
<button type="button" class="btn btn-warning btn-sm" {{action 'createrecord'}}>Case</button>
Then in the controllers i have defined this action:
Here is my controller code:
actions:{
createrecord:function(){
return this.store.createRecord('rulecase');
}
}
But every time when i click on the add button it creates an empty record with id =null because on which i am not able to iterate over model.ruleCase.
How to overcome this problem????

If what you're wanting is to be able to associate the new rulecase to the model, you don't need an ID for it.
Modify the createRecord method and push it to model.ruleCase
createrecord:function(){
const newRulecase = this.store.createRecord('rulecase');
model.get('ruleCase').pushObject(newRulecase)
return newRulecase;
}
If there's some other reason that's causing you to need an ID, you can generate one on the client side using generateIdForRecord. You'll need to generate an adapter file for the ruleCase model and apply the logic for the ID.

Related

How to get the current record_id to access specific model records in javascript odoo

On a record's XML button click I'm returning a client action qweb wizard with javascript functions. After running some javascript functions I need to save the results in a specific record(The record from which this wizard was opened with a button click). All my functions work but I do not know how to fetch the ID of the record so I'm not able to save the data to that specific record. How to fetch the ID of the current record in Javascript?
The wizard is a QWEB Javascript Client Action type.
XML Button:
<button name="open_bio_window" string="Bio" type="object" class="oe_highlight"/>
Python method I use to call the wizard:
#api.multi
def open_bio_window(self):
return {
'res_model': 'bank.agent',
'type': 'ir.actions.client',
'tag': 'action_biometric_page',
'target': 'new'
}
Javascript Sample:
events: {
'click .discoverService': 'discoverService',
},
discoverService: function(ev){
// do something
var endPoint = "ENDPOINT";
// save endPoint to the record that called this method
},
How to save endPoint to field end_point in parent record?
Qweb Template Sample:
<t t-name="bank_model.BioCapture">
<h3>Bio Capture</h3>
<div>Please verify Device is connected! Press 'Start' after
verification.
</div>
<br/>
<img src="/bank_model/static/description/device_ready.png"/>
<br/>
<br/>
<div>
<button class="btn btn-info discoverService btnheight">Start</button>
</div>
</t>
I solved it by passing the ID as a parameter in python method call.
#api.multi
def open_bio_window(self):
for record in self:
return {
'res_model': 'bank.agent',
'type': 'ir.actions.client',
'tag': 'action_biometric_page',
'target': 'new',
'params': {'rec_id': record.id}
}
Then access that parameter in javascript.
init: function (parent, context) {
this._super(parent, context);
this.rec_id = context.params.rec_id;
this.dashboards_templates = ['bank_model.BioCapture'];
},

Angular: Keep model data in sync with database

i'm making my first weapons with Angular. I cannot understand the best way to handle data modifications in model and store it in the database, e.g:
In controller:
$scope.items = [
{ id: 1, status: 0, data: 'Foo Item' }
{ id: 2, status: 0, data: 'Foooo' }
{ id: 3, status: 1, data: 'OooItem' }
];
In view:
<tr ng-repeat="item in items | orderBy:'-id'">
<td>{{item.id}}</td>
<td>{{item.data}}</td>
<td>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="status(item.id, 1)">Acept</button>
<button type="button" class="btn btn-default" ng-click="status(item.id, 2)">Reject</button>
</div>
</td>
</tr>
What should I do to update the item status to 1 or 2? Make a call to the server, and then retrieve the new model? Update the model data with JS, and make the call? Is any way to do it automatic? Angular provide some method to access to the current "clicked" item to update the prop (status in this case)?
Hope I was clear.
Thanks.
EDIT: So, based on Dr Jones comment, i write this using underscore.
function status(id, status) {
$http.put().then()....
//after success response, update the model
item = _.find($scope.items, function (rw) {
return rw.id == id
});
item.status = status;
}
This is a valid and correct way to this?
The answer is that it's really up to you. As with all async programming you have the option to 'auto-sync' or sync as a result of a user event (e.g. hitting a save button). It really depends on how your app is designed.
Frameworks like firebase (angular-fire lib) have handy built in auto-sync functionality, alternatively the REST Post/Put request is a more traditional design pattern.

Emberjs - model hook returns null from BelongsTo relationship

I have a form within the new-phone route which populates a phone model. This model has a belongsTo relationship with the client.
App.Router.map(function() {
this.resource("client", { path: "/client/:id" }, function(){
this.resource("phone", function(){
this.route("new-phone")
})
})
})
App.Client = DS.Model.extend({
name: DS.attr(),
phone: DS.belongsTo("Phone", { async: true })
});
App.Phone = DS.Model.extend({
name: DS.attr(),
model: DS.attr(),
year: DS.attr()
});
When I complete the form, the response from the server comes back correctly with the newly created record.
I'm getting data from JSON driven API.
So I'm posting to:
POST: /api/client/1/phone
I have set the transition to go back to the phone.index page (after the save is complete) which in turn (should) fire the model hook (GET request: /api/client/1/phone) and get the new data for the (phones.index) page. But for some reason, I get a 'data is null' error from Ember. It doesn't even seem to make the request before this error appears.
If I use the HTTP requester outside of the Ember app, the data appears.
App.ClientRoute = Ember.Route.extend({
model: function(){
return this.store.find("client", 1)
}
});
App.PhoneIndexRoute = Ember.Route.extend({
model: function(){
return this.modelFor("client").get("phone").then(function(data){
//Reload to manually get new data
return data.reload();
});
}
})
This is the version of Ember I'm using:
DEBUG: Ember : 1.8.1
DEBUG: Ember Data : 1.0.0-beta.11
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery : 1.10.2
I dont think you need a new route to show a form for person's phone. Instead make a property to toggle when user clicks for phone form
Let's say your template looks like this
/user/1.hbs
{{model.user_name}} {{model.first_name}}
{{model.phone.number}}
{{#if showPhoneForm}}
<div class="form">
{{input value=model.phone.number placeholder="phone nr"}}
</div>
<div class="button" {{action "saveUser"}}> Save </button> // Save form data, hide user form, updaet user phone data
{{else}}
<div class="button" {{action "makePhoneForm"}}> Add phone </button> // Create form for user
{{/if}}
controllers/user/
showPhoneForm: false,
actions: {
makePhoneForm: function() {
this.set('showPhoneForm', true);
},
saveUser: function() {
this.get('model.phone').then(function(phoneRecord) {
phoneRecord.save().then(function(){
this.set('showPhoneForm', false);
}.bind(this):
}
}

Saving nested data via angular

I'm trying to save the contents of a form into a hierarchical data structure:
$scope.milestones = [
{milestoneName: "milestone 1",
id:"milestoneOne",
headingID:"headingOne",
panelClass:"in",
tasks:[
{
taskSubject:"Get cost agreement confirmation",
category:"#7FFF00",
dueDate:"July 5, 2015",
repeat: true,
assignee:"Jiman Ilitad",
estHours:"3"},
{
taskSubject:"Get cost agreement confirmation",
category:"#7FFF00",
dueDate:"July 5, 2015",
repeat: true,
assignee:"Jiman Ilitad",
estHours:"3"}
]}
];
I'm using ng-repeat to display milestones and then within each of the milestones I have tasks. Each milestone can have one or more tasks added to it via a basic html form where each input corresponds with a value in the push.
Here is the script which defines the push:
$scope.addTask = function(index){
$scope.milestones.tasks.push({
taskSubject: $scope.index.formTaskSubject,
category: $scope.index.formCategory,
dueDate: $scope.index.formDate,
repeat: $scope.index.formRepeat,
assignee: $scope.index.formAssignee,
estHours: $scope.index.formEstTime
})
};
I'm currently getting an error: TypeError: Cannot read property 'push' of undefined
This error means that you're trying to call the method push on something that doesn't exist. Since $scope.milestones is an array, you need to specify which element in that array you're trying to add a task to.
Based on your plunker, you just need to call addTask() with an additional parameter specifying the index of the milestone you wish to modify.
In your ng-click, pass in an index to the milestone. For example, change:
<a class="btn btn-primary" ng-click="addTask()">Save</a>
To:
<a class="btn btn-primary" ng-click="addTask($index)">Save</a>
The above assumes that $index is the index to your $scope.milestones array, which is assigned by ng-repeat="milestone in milestones". It can easily change if you nest ng-repeats, breaking your code.
To avoid this, just pass the milestone object itself directly into addTask.
In your HTML:
<div ... ng-repeat="milestone in milestones" ...>
...
<a ... ng-click="addTaskTo(milestone)" ...>Save</a>
...
In your controller:
$scope.addTaskTo = function(milestone) {
milestone.tasks.push(...);

Backbone.js - how to handle "login"?

Hi I'm trying to wrap my head around backbone.js for some days now but since this is my first MVC Framework, it's pretty hard.
I can easily get my Collections to work, fetching data from the server etc, but it all depends on first "logging" in per API-Key. I just don't know how to model this with a good MVC approach. (btw: I can't use the Router/Controller because it's a Chrome Extension)
The Flow looks like this:
Start Extension
Is there an API-Key in localStorage?
No => Display a input field and a save button which saves the key to localStorage; Yes => proceed with the Application:
App......
The only way I could think of it is putting it all together in a big View... but I guess since I am fairly new to this there are surely some better approaches.
You can create a model that maintains the state of the user's login status and a view that renders a different template depending on that status. The view can show the "input field" template if the user is not logged in and a different template if the user is. I would keep all access to localStorage in the Model because the View should not be concerned with persistence. The view should probably not be concerned with the API Key as well, and that's why I have my view binding to the model's loggedIn change ('change:loggedIn') instead of apiKey change...although I am showing the API key in one of my templates for demonstration purpose only. Here's my very simplified sample. Note that I didn't bother with validating the API Key, but you'll probably want to:
Templates:
<script id="logged_in" type="text/html">
You're logged in. Your API key is <%= escape('apiKey') %>. Let's proceed with the application...
</script>
<script id="not_logged_in" type="text/html">
<form class="api_key">
API Key: <input name="api_key" type="text" value="" />
<button type="sumit">Submit</button>
</form>
</script>
Backbone Model and View:
var LoginStatus = Backbone.Model.extend({
defaults: {
loggedIn: false,
apiKey: null
},
initialize: function () {
this.bind('change:apiKey', this.onApiKeyChange, this);
this.set({'apiKey': localStorage.getItem('apiKey')});
},
onApiKeyChange: function (status, apiKey) {
this.set({'loggedIn': !!apiKey});
},
setApiKey: function(apiKey) {
localStorage.setItem('apiKey', apiKey)
this.set({'apiKey': apiKey});
}
});
var AppView = Backbone.View.extend({
_loggedInTemplate: _.template($('#logged_in').html()),
_notLoggedInTemplate: _.template($('#not_logged_in').html()),
initialize: function () {
this.model.bind('change:loggedIn', this.render, this);
},
events: {
'submit .api_key': 'onApiKeySubmit'
},
onApiKeySubmit: function(e){
e.preventDefault();
this.model.setApiKey(this.$('input[name=api_key]').val());
},
render: function () {
if (this.model.get('loggedIn')) {
$(this.el).empty().html(this._loggedInTemplate(this.model));
} else {
$(this.el).empty().html(this._notLoggedInTemplate(this.model));
}
return this;
}
});
var view = new AppView({model: new LoginStatus()});
$('body').append(view.render().el);

Categories

Resources