How to load dynamically a modal with Spring MVC and ThymeLeaf

0

In the image I have two rows that each represent an object of type FisicHost in my program.

Clicking on any of the two rows opens a modal with the credentials of the relevant FisicHost.

The problem is that indistinctly FisicHost (the line) in which click, the modal that opens brings me ALL existing credentials, and not those of ESE Fisic Host in particular.

FisicHost class:

@Entity
@Transactional
public class FisicHost {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch=FetchType.EAGER)
    private Datacenter datacenter;

    @OneToMany(mappedBy = "fisicHost")
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Credential> credentials;

    private String name;
    private String ip;
    private String operatingSystem;
    private String notes;

    public FisicHost(){

    }

    public FisicHost(Long id, Datacenter datacenter, List<Credential> credentials, String name, String ip, String operatingSystem, String notes) {
        this.id = id;
        this.datacenter = datacenter;
        this.credentials = credentials;
        this.name = name;
        this.ip = ip;
        this.operatingSystem = operatingSystem;
        this.notes = notes;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Datacenter getDatacenter() {
        return datacenter;
    }

    public void setDatacenter(Datacenter datacenter) {
        this.datacenter = datacenter;
    }

    public List<Credential> getCredentials() {
        return credentials;
    }

    public void setCredentials(List<Credential> credentials) {
        this.credentials = credentials;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getOperatingSystem() {
        return operatingSystem;
    }

    public void setOperatingSystem(String operatingSystem) {
        this.operatingSystem = operatingSystem;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }
}

How am I doing this?

This is the controller method that handles that view:

@RequestMapping(value = "/chosenDatacenter", method = RequestMethod.POST)
public String datacenterPostHandler(@RequestParam("datacenterList") String name, ModelMap modelMap){
    List<Datacenter> allDatacenters = datacenterDao.getAllDatacenters();
    for (Datacenter dc : allDatacenters) {
        if (dc.getName().equals(name)) {
        modelMap.put("datacenter", dc);
        if(dc.getFisicHostList().size() != 0) {
            List<FisicHost> datacenterFisicHosts = dc.getFisicHostList();
            modelMap.put("datacenterFisicHosts", datacenterFisicHosts);
            for(FisicHost fh : datacenterFisicHosts){
                if(fh.getCredentials().size() != 0){
                    modelMap.put("fisicHostCredentialsList", credentialDao.getAllCredentialsByFisicHost(fh));
                }
            }
        }
        return "chosenDatacenter";
        }
    }
        return null;
}

GetAllCredentialsByFisicHost method of the CredentialDaoImpl class:

@Override
public List<Credential> getAllCredentialsByFisicHost(FisicHost fisicHost) {
    // Open a session
    Session session = sessionFactory.openSession();

    Criteria c = session.createCriteria(Credential.class).add(Restrictions.eq("fisicHost.id", fisicHost.getId()));

    List<Credential> allCredentials = c.list();

    // Close the session
    session.close();

    return allCredentials;
}

Debugging, I realize that in this controller loop:

for(FisicHost fh : datacenterFisicHosts){
                if(fh.getCredentials().size() != 0){
                    modelMap.put("fisicHostCredentialsList", credentialDao.getAllCredentialsByFisicHost(fh));
                }
            }

I always take the last FisicHost from the loop, and then call the getAllCredentialsByFisicHost () method with that same FisicHost, so the credentials that are loaded in the manners of the view are always those of this last FisicHost !!

That is, in this line of the loop:

modelMap.put("fisicHostCredentialsList", credentialDao.getAllCredentialsByFisicHost(fh));

the value "fisicHostCredentialList" will ALWAYS take the credentials of the last FisicHost with which the cycle ends !!!

Therefore the values of the view will always be based on that FisicHost to obtain the credentials, which I do not want, what I want is for the FisicHost to be taken depending on the user's click on the view.

This is my view, it's armed with ThymeLeaf :

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>Generic View</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap/bootstrap.min.css}" />
    <link rel="stylesheet" th:href="@{/css/choosenDatacenter.css}" />
</head>

<body>

<form id="form" action="#" th:object="${datacenterFisicHosts}" method="post">

    <table>
        <tr class="row">
            <th class="tableHeader">Nombre</th>
            <th class="tableHeader">IP</th>
            <th class="tableHeaders">Sistema Operativo</th>
            <th class="tableHeaders">Notas</th>
        </tr>

        <th:block th:each="fh : ${datacenterFisicHosts}">
        <div id="fila">
            <tr class="row">
                <td id="fisicHostName" th:text="${fh.name}"></td>
                <td id="fisicHostIp" th:text="${fh.ip}"></td>
                <td id="fisicHostOS" th:text="${fh.operatingSystem}"></td>
                <td id="fisicHostNotes" th:text="${fh.notes}"></td>
            </tr>
        </div>
        </th:block>
    </table>


</form>


<!-- Modal -->
<div class="modal fade" id="modalCredenciales" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="modal-title">Credenciales</h5>
            </div>
            <div class="modal-body">
                <table>
                    <tr class="row">
                        <th class="tableHeader">Usuario</th>
                        <th class="tableHeader">Clave</th>
                        <th class="tableHeaders">Notas</th>
                    </tr>

                    <th:block th:each="credential : ${fisicHostCredentialsList}">
                        <tr class="row">
                            <td id="credentialUser" th:text="${credential.user}"></td>
                            <td id="credentialPassword" th:text="${credential.password}"></td>
                            <td id="credentialRole" th:text="${credential.notes}"></td>
                        </tr>
                    </th:block>
                </table>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
            </div>
        </div>
    </div>
</div>

<script th:src="@{js/jquery-1.11.3.js}"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script th:src="@{js/chosenDatacenter.js}"></script>
</body>
</html>

Well, I know what the problem is, but not the solution !!!

If my problem is understood, someone could tell me how I can do the logic so that when the user clicks on a FisicHost view, the modality is opened with the credentials of ESE FisicHost and it does not bring me the credentials of ALL FisicHost ??

The problem is also that once the user clicked on the view, the modal data was previously loaded in the back-end, so it should be a kind of AJAX but only for the modal, but as the modal is within sight ... I do not know what to do ... as you can see I do not have a lot of experience programming, so I ask. Thanks !!

    
asked by Nacho Zve De La Torre 07.11.2018 в 15:27
source

1 answer

1

I have not tried the code, so it most likely will not work the first time with just the one, but this should give you an idea of what you have to do to use JQuery.

Controller.java

@RequestMapping(value = "/chosenDatacenter", method = RequestMethod.POST)
public String datacenterPostHandler(@RequestParam("datacenterList") String name, ModelMap modelMap){
    List<Datacenter> allDatacenters = datacenterDao.getAllDatacenters();
    for (Datacenter dc : allDatacenters) {        
        if (dc.getName().equals(name)) {
            modelMap.put("datacenter", dc);

            List<FisicHost> datacenterFisicHosts = dc.getFisicHostList();
            modelMap.put("datacenterFisicHosts", datacenterFisicHosts);

            return "chosenDatacenter";
        }
    }
    return null;
}


@RequestMapping(value = "/fisicHost/{id}/credentials", method = RequestMethod.GET, produces = APPLICATION_JSON_UTF8_VALUE)
public List<Credentials> credentialsByFisicHost(@PathVariable(value = "id") final Long fisicHostId, ModelMap modelMap){
     Optional<FisicHost> optionalFisicHost = fisicHostDao.findById(fisicHostId);

     if (optionalFisicHost.isEmpty()) {
          // Responder con 404
     }

     FisicHost fisicHost = optionalFisicHost.get();

     return fisicHost.getCredentials();
}

FisicHostsTable.html

<table id="fisicHostsTable">
    <tr class="row">
        <th class="tableHeader">Nombre</th>
        <th class="tableHeader">IP</th>
        <th class="tableHeaders">Sistema Operativo</th>
        <th class="tableHeaders">Notas</th>
    </tr>

    <th:block th:each="fh : ${datacenterFisicHosts}">
    <div>
        <tr class="row">
            <td id="fisicHostName" th:text="${fh.name}"></td>
            <td id="fisicHostIp" th:text="${fh.ip}"></td>
            <td id="fisicHostOS" th:text="${fh.operatingSystem}"></td>
            <td id="fisicHostNotes" th:text="${fh.notes}"></td>
            <td><button class="fisicHostButton" th:attr="data-fisic-host-id=${fh.id}"></button></td>
        </tr>
    </div>
    </th:block>
</table>

Modal.html

<div class="modal fade" id="modalCredenciales" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="modal-title">Credenciales</h5>
            </div>
            <div class="modal-body">
                <table id="credentialsTable">
                    <tr class="row">
                        <th class="tableHeader">Usuario</th>
                        <th class="tableHeader">Clave</th>
                        <th class="tableHeaders">Notas</th>
                    </tr>
                </table>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
            </div>
        </div>
    </div>
</div>

Jquery.JS

$(".fisicHostButton").click(function(){
    var fisicHostId = $(this).data('fisic-host-id');
    $.get( "/fisicHost/" + fisicHostId + "/credentials", function( data ) {
        console.log(data);
        $("#credentialsTable > .credential'").remove();

        for (i = 0; i < data.length; ++i) {
            var fisicHost = data[i];

            var new_row = document.createElement('tr');
            new_row.className = "row credential";

            var nameCol = document.createElement('td');
            nameCol.textContent = fisicHost["name"];
            new_row.append(nameCol)

            var hostIpCol = document.createElement('td');
            hostIpCol.textContent = fisicHost["ip"];
            new_row.append(hostIpCol)

            var hostOsCol = document.createElement('td');
            hostOsCol.textContent = fisicHost["operatingSystem"];
            new_row.append(hostOsCol)

            var hostNotesCol = document.createElement('td');
            hostNotesCol.textContent = fisicHost["notes"];
            new_row.append(hostNotesCol)

            $("#credentialsTable").append(new_row);
        }

        $('#modalCredenciales').modal('show');
    }).fail(function(xhr, status, error) {
        console.error(error);
        alert('No se pudieron cargar las credenciales.');
    });
});

JQuery.remove information and JQuery selection of children .

Tell me any questions or concerns you have.

    
answered by 07.11.2018 / 20:15
source