Aron Lorincz
Aron Lorincz

Reputation: 1707

Odoo - prevent button from closing wizard

I have a transient model that serves as a dialog. In my form view I have a button like this:

<footer states="partnerId">
   <button name="check_tax_id" string="Tovább" type="object"/>
</footer>

The button invokes this function (I can confirm it actually invokes):

@api.one
    def check_tax_id(self, context=None):
        self.state = "partnerDetails"

        return None;

My problem is that the dialog window is closed immediately once I click this button! What am I doing wrong?

Upvotes: 15

Views: 20860

Answers (7)

Muhammad Awais
Muhammad Awais

Reputation: 365

In Odoo16

def _action_open_modal(self):
    """Allow to keep the wizard modal open after executing the action."""
    return {
        'name': _('Portal Access Management'),
        'type': 'ir.actions.act_window',
        'res_model': 'portal.wizard',
        'view_type': 'form',
        'view_mode': 'form',
        'res_id': self.id,
        'target': 'new',
    }

addons/portal/wizard/portal_wizard.py

Upvotes: 0

ChesuCR
ChesuCR

Reputation: 9620

Solution 0

@api.multi
def check_tax_id(self):
    self.ensure_one()
    self.name = "New name"
    return {
        "type": "ir.actions.do_nothing",
    }

This solution was provided here by Tadeusz Karpinski.

Solution 1

You can return a new form with the same record id.

@api.multi
def check_tax_id(self):
    self.ensure_one()
    self.name = "New name"
    return {
        'context': self.env.context,
        'view_type': 'form',
        'view_mode': 'form',
        'res_model': 'model_name',
        'res_id': self.id,
        'view_id': False,
        'type': 'ir.actions.act_window',
        'target': 'new',
    }

Solution 2

You can create a widget in jQuery. This will open the wizard and you can assign the behaviour you want to the buttons manually. You can use the call function to call python functions as well:

[...]

new instance.web.Dialog(this, { 
    title: _t("Title"), 
    width: '95%', 
    buttons: [
          { text: _t("First button"), click: function() { self.first_button(); }}, 
          { text: _t("Second button"), click: function() { self.second_button(); }},
          { text: _t("Close"), click: function() {  dialog.close(); }},                       
      ],
});

[...]

Solution 3

Of course you can override the create method as well to avoid the creation of the record in some cases

Solution 4

One last option. Create a workflow with a state field. Create workflow buttons in order to send signals to change the state. You can show or hide the rest of the fields using the attrs attribute and the state field. But I do not know if that would adapt to your needs.

Upvotes: 36

simahawk
simahawk

Reputation: 2431

yesterday I bumped on this same issue. I needed to show a button to do something without submitting the whole wizaard. I worked around it by not using a button at all. It's pretty simple and effective. What you need:

  1. a boolean flag in your wizard model
  2. an onchange attached to the flag (that replaces you sumbmit function)
  3. replace the button in the view w/ the flag w/ invisible="1" and a label to be styled as a button

Here's the code:

source_it = fields.Boolean(string='Source')
[...]
def action_source(self):
    # do stuff

@api.onchange('source_it')
def onchange_source_it(self):
    if self.env.context.get('sourcing_now') or not self.source_it:
        return
    self.action_source()
[...]
<label for="source_it" class="pull-left btn btn-success" />
<field name="source_it" invisible="1" />

The trick works because when a label has for attribute is going to act like the checkbox itself, so if you click on the label you are actually switching the checkbox.

Upvotes: 3

user3778322
user3778322

Reputation: 61

The simplest this to do is :

@api.multi
def null_action(self):
    return {
        "type": "set_scrollTop",
    }

As the type is used to call any method on the class ActionManager (javascript)

It's better than "type": "ir.actions.do_nothing" which generate an exception (this attribute doesn't exist)

Upvotes: 6

user2529782
user2529782

Reputation:

In my case this code works.

@api.multi
def test(self):
    l = logging.getLogger()
    l.warn("xD")
    return {
        "type": "ir.actions.do_nothing",
    }

Upvotes: 9

Phillip Stack
Phillip Stack

Reputation: 3378

What you can do is have the button open another wizard passing context with all the values entered into the first wizard. This allows you to execute some function ie. your button. And maintain the state of your wizard. So the default value for fields in your wizard must check context first and fallback to something else.

Here is an example:

class MyWizard(models.TransientModel):
    _name = 'myaddon.mywizard'

    def _get_default_char(self):
        return self._context.get('mychar',"")

    mychar = fields.Char(string="My Char", default=_get_default_char)

    @api.multi
    def my_button(self):
        # Execute Function Here
        # reload wizard with context

        return {
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'myaddon.mywizard',
            'type': 'ir.actions.act_window',
            'target': 'new',
            'context': '{"mychar":'HELLO WORLD'}',
        }

Upvotes: 1

Hamza Salem
Hamza Salem

Reputation: 11

on odoo 7

def traszero(self ,cr ,uid ,ids ,context=None):
        data_obj = self.pool.get('stock.return.picking.line')
        ret_wizard = self.browse(cr, uid, ids, context=context)
        if ret_wizard.product_return_moves:
            line_ids = ret_wizard.product_return_moves.mapped('id')
            data_obj.write(cr, uid, line_ids, {'quantity': 0}, context=context)
        return {'name':"Return Shipment",
            'res_model':"stock.return.picking",
            'src_model':"stock.picking",
            'view_mode':"form",
            'target':"new",
            'key2':"client_action_multi",
            'multi':"True",
            'res_id':ids[0],
            'type': 'ir.actions.act_window',
            }

Upvotes: 0

Related Questions