Use querySelector to target the <p> directly:

document.querySelector('#MyCssId p').textContent = "Something";

document.querySelector('#MyCssId p').innerHTML= "Something<span class=\"MyClass\">something else</span>";
If your innerHTML includes double quotes or newlines

You can use backticks instead of quotes:

document.querySelector('#MyCssId p').innerHTML= `Something<span class="MyClass">
something else
</span>
`;
Checking if the ID exists
const el = document.querySelector('#MyCssId p');
if (el)
  el.textContent = "Something";

If the text you are inserting has special characters, line breaks, etc

Because you are inserting into javascript, json_encode is the best solution. (Note there are no surrounding quotes, json_encode provides these).

  $ConvertedText = json_encode($MyText);
  $HtmlOutput .= <<<_END
    <style>
      #MyCssId p {
        white-space: pre-line;
      }
    </style>
    <script>
document.querySelector('#MyCssId p').innerHTML= $ConvertedText;
    </script>
_END;

The white-space: pre-line; is needed to ensure line breaks get shown, in elementor you can use this on the target text file custom CSS:

selector p {
    white-space: pre-line;
}

Why document.getElementById(‘MyCssId’).textContent doesn’t work

When you apply an ID to an Elementor widget, it is often applied a level up from the actual displayed text, e.g. for ID=”MyCssId” applied to a Text Editor widget:

<div class="elementor-element elementor-element-9c45b00 elementor-widget elementor-widget-text-editor" data-id="9c45b00" data-element_type="widget" id="MyCssId" data-widget_type="text-editor.default">
  <div class="elementor-widget-container">
    <p style="text-align: center;">$##.##</p>
  </div>
</div>

If you use this on the ID:

document.getElementById('MyCssId').textContent = "£12.34";

You will remove the <div> and <p> surrounding the target text, resulting in styling being lost.